prime-dev-cli 1.0.11-beta.2 → 1.0.12-beta.1
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/dist/server/.next/BUILD_ID +1 -1
- package/dist/server/.next/app-build-manifest.json +5 -5
- package/dist/server/.next/app-path-routes-manifest.json +1 -0
- package/dist/server/.next/build-manifest.json +6 -6
- package/dist/server/.next/cache/.tsbuildinfo +1 -1
- package/dist/server/.next/cache/eslint/.cache_1qa5vxt +1 -1
- package/dist/server/.next/fallback-build-manifest.json +6 -6
- package/dist/server/.next/next-minimal-server.js.nft.json +1 -1
- package/dist/server/.next/next-server.js.nft.json +1 -1
- package/dist/server/.next/prerender-manifest.json +9 -9
- package/dist/server/.next/server/app/_not-found/page/app-build-manifest.json +1 -1
- package/dist/server/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/server/.next/server/app/_not-found.html +1 -1
- package/dist/server/.next/server/app/_not-found.rsc +2 -2
- package/dist/server/.next/server/app/api/all-projects-envs/route.js +1 -1
- package/dist/server/.next/server/app/api/all-projects-envs/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/check-mock-intercept/route.js +1 -1
- package/dist/server/.next/server/app/api/check-mock-intercept/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/check-workspace/route.js +1 -1
- package/dist/server/.next/server/app/api/check-workspace/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/cleanup-mock/route.js +1 -1
- package/dist/server/.next/server/app/api/cleanup-mock/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/current-branch/route/app-build-manifest.json +11 -0
- package/dist/server/.next/server/app/api/current-branch/route/app-paths-manifest.json +3 -0
- package/dist/server/.next/server/app/api/current-branch/route/build-manifest.json +17 -0
- package/dist/server/.next/server/app/api/current-branch/route/next-font-manifest.json +6 -0
- package/dist/server/.next/server/app/api/current-branch/route/react-loadable-manifest.json +1 -0
- package/dist/server/.next/server/app/api/current-branch/route/server-reference-manifest.json +4 -0
- package/dist/server/.next/server/app/api/current-branch/route.js +8 -0
- package/dist/server/.next/server/app/api/current-branch/route.js.map +5 -0
- package/dist/server/.next/server/app/api/current-branch/route.js.nft.json +1 -0
- package/dist/server/.next/server/app/api/current-branch/route_client-reference-manifest.js +2 -0
- package/dist/server/.next/server/app/api/delete-mock-api/route.js +1 -1
- package/dist/server/.next/server/app/api/delete-mock-api/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/get-mock-data/route.js +1 -1
- package/dist/server/.next/server/app/api/get-mock-data/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/initialize-workspace/route.js +1 -1
- package/dist/server/.next/server/app/api/initialize-workspace/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/microapp-proxy-change-stream/route.js +1 -1
- package/dist/server/.next/server/app/api/microapp-proxy-change-stream/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/microapp-proxy-config/route.js +1 -1
- package/dist/server/.next/server/app/api/microapp-proxy-config/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/mock-file/route.js +1 -1
- package/dist/server/.next/server/app/api/mock-file/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/mock-file-content/route.js +1 -1
- package/dist/server/.next/server/app/api/mock-file-content/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/mock-open-status/route.js +1 -1
- package/dist/server/.next/server/app/api/mock-open-status/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/mock-setting/route.js +1 -1
- package/dist/server/.next/server/app/api/mock-setting/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/open-all-mock/route.js +1 -1
- package/dist/server/.next/server/app/api/open-all-mock/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/process/start/route.js +1 -1
- package/dist/server/.next/server/app/api/process/start/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/process/status/route.js +1 -1
- package/dist/server/.next/server/app/api/process/status/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/project-config/route.js +1 -1
- package/dist/server/.next/server/app/api/project-config/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/retry-project/route.js +1 -1
- package/dist/server/.next/server/app/api/retry-project/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/configuration/page/app-build-manifest.json +2 -2
- package/dist/server/.next/server/app/configuration/page.js.nft.json +1 -1
- package/dist/server/.next/server/app/configuration/page_client-reference-manifest.js +1 -1
- package/dist/server/.next/server/app/configuration.html +1 -1
- package/dist/server/.next/server/app/configuration.rsc +3 -3
- package/dist/server/.next/server/app/index.html +1 -1
- package/dist/server/.next/server/app/index.rsc +2 -2
- package/dist/server/.next/server/app/initialization/page/app-build-manifest.json +1 -1
- package/dist/server/.next/server/app/initialization/page_client-reference-manifest.js +1 -1
- package/dist/server/.next/server/app/initialization.html +1 -1
- package/dist/server/.next/server/app/initialization.rsc +2 -2
- package/dist/server/.next/server/app/page/app-build-manifest.json +1 -1
- package/dist/server/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/server/.next/server/app-paths-manifest.json +1 -0
- package/dist/server/.next/server/chunks/{[root-of-the-server]__27f3b464._.js → [root-of-the-server]__07de450e._.js} +2 -2
- package/dist/server/.next/server/chunks/{[root-of-the-server]__27f3b464._.js.map → [root-of-the-server]__07de450e._.js.map} +1 -1
- package/dist/server/.next/server/chunks/{[root-of-the-server]__ec631eb4._.js → [root-of-the-server]__09808308._.js} +2 -2
- package/dist/server/.next/server/chunks/{[root-of-the-server]__ec631eb4._.js.map → [root-of-the-server]__09808308._.js.map} +1 -1
- package/dist/server/.next/server/chunks/{[root-of-the-server]__dfe36c1a._.js → [root-of-the-server]__09914a79._.js} +2 -2
- package/dist/server/.next/server/chunks/{[root-of-the-server]__dfe36c1a._.js.map → [root-of-the-server]__09914a79._.js.map} +1 -1
- package/dist/server/.next/server/chunks/{[root-of-the-server]__c513ec4a._.js → [root-of-the-server]__42bc7b42._.js} +2 -2
- package/dist/server/.next/server/chunks/{[root-of-the-server]__c513ec4a._.js.map → [root-of-the-server]__42bc7b42._.js.map} +1 -1
- package/dist/server/.next/server/chunks/{[root-of-the-server]__b68e0025._.js → [root-of-the-server]__4dc677cb._.js} +2 -2
- package/dist/server/.next/server/chunks/{[root-of-the-server]__b68e0025._.js.map → [root-of-the-server]__4dc677cb._.js.map} +1 -1
- package/dist/server/.next/server/chunks/{[root-of-the-server]__92625851._.js → [root-of-the-server]__52d487d8._.js} +2 -2
- package/dist/server/.next/server/chunks/{[root-of-the-server]__92625851._.js.map → [root-of-the-server]__52d487d8._.js.map} +1 -1
- package/dist/server/.next/server/chunks/{[root-of-the-server]__7a46f739._.js → [root-of-the-server]__582946e6._.js} +2 -2
- package/dist/server/.next/server/chunks/{[root-of-the-server]__7a46f739._.js.map → [root-of-the-server]__582946e6._.js.map} +1 -1
- package/dist/server/.next/server/chunks/{[root-of-the-server]__0111ac14._.js → [root-of-the-server]__5cddc64c._.js} +2 -2
- package/dist/server/.next/server/chunks/{[root-of-the-server]__0111ac14._.js.map → [root-of-the-server]__5cddc64c._.js.map} +1 -1
- package/dist/server/.next/server/chunks/{[root-of-the-server]__63462bcb._.js → [root-of-the-server]__802aba2d._.js} +2 -2
- package/dist/server/.next/server/chunks/{[root-of-the-server]__63462bcb._.js.map → [root-of-the-server]__802aba2d._.js.map} +1 -1
- package/dist/server/.next/server/chunks/{[root-of-the-server]__9544d1f9._.js → [root-of-the-server]__837d58ae._.js} +2 -2
- package/dist/server/.next/server/chunks/{[root-of-the-server]__9544d1f9._.js.map → [root-of-the-server]__837d58ae._.js.map} +1 -1
- package/dist/server/.next/server/chunks/{[root-of-the-server]__c43c9880._.js → [root-of-the-server]__933f7077._.js} +2 -2
- package/dist/server/.next/server/chunks/{[root-of-the-server]__c43c9880._.js.map → [root-of-the-server]__933f7077._.js.map} +1 -1
- package/dist/server/.next/server/chunks/[root-of-the-server]__94e10604._.js +3 -0
- package/dist/server/.next/server/chunks/[root-of-the-server]__94e10604._.js.map +1 -0
- package/dist/server/.next/server/chunks/{[root-of-the-server]__84542811._.js → [root-of-the-server]__a6211ee0._.js} +2 -2
- package/dist/server/.next/server/chunks/{[root-of-the-server]__84542811._.js.map → [root-of-the-server]__a6211ee0._.js.map} +1 -1
- package/dist/server/.next/server/chunks/{[root-of-the-server]__29969c0b._.js → [root-of-the-server]__aca25fcf._.js} +2 -2
- package/dist/server/.next/server/chunks/{[root-of-the-server]__29969c0b._.js.map → [root-of-the-server]__aca25fcf._.js.map} +1 -1
- package/dist/server/.next/server/chunks/{[root-of-the-server]__3da8edfd._.js → [root-of-the-server]__be3de126._.js} +2 -2
- package/dist/server/.next/server/chunks/{[root-of-the-server]__3da8edfd._.js.map → [root-of-the-server]__be3de126._.js.map} +1 -1
- package/dist/server/.next/server/chunks/{[root-of-the-server]__fab72f0c._.js → [root-of-the-server]__da89e112._.js} +2 -2
- package/dist/server/.next/server/chunks/{[root-of-the-server]__fab72f0c._.js.map → [root-of-the-server]__da89e112._.js.map} +1 -1
- package/dist/server/.next/server/chunks/[root-of-the-server]__e07d75ff._.js +3 -0
- package/dist/server/.next/server/chunks/[root-of-the-server]__e07d75ff._.js.map +1 -0
- package/dist/server/.next/server/chunks/{[root-of-the-server]__1efea51d._.js → [root-of-the-server]__e301c560._.js} +2 -2
- package/dist/server/.next/server/chunks/{[root-of-the-server]__1efea51d._.js.map → [root-of-the-server]__e301c560._.js.map} +1 -1
- package/dist/server/.next/server/chunks/{[root-of-the-server]__525f44e0._.js → [root-of-the-server]__ef09a48e._.js} +2 -2
- package/dist/server/.next/server/chunks/{[root-of-the-server]__525f44e0._.js.map → [root-of-the-server]__ef09a48e._.js.map} +1 -1
- package/dist/server/.next/server/chunks/ssr/{_2488faea._.js → _bb352729._.js} +3 -3
- package/dist/server/.next/server/chunks/ssr/_bb352729._.js.map +1 -0
- package/dist/server/.next/server/middleware-build-manifest.js +4 -4
- package/dist/server/.next/server/pages/404.html +1 -1
- package/dist/server/.next/server/pages/500.html +1 -1
- package/dist/server/.next/server/pages/_app/build-manifest.json +2 -2
- package/dist/server/.next/server/pages/_error/build-manifest.json +2 -2
- package/dist/server/.next/static/chunks/{d5028315079b40b4.js → 2befba13bed43c5f.js} +1 -1
- package/dist/server/.next/static/chunks/344b0062191ace22.css.map +1 -0
- package/dist/server/.next/static/chunks/{249486689b72c55c.js → 4cbec079b6e3e189.js} +2 -2
- package/dist/server/.next/static/chunks/6c91d5f280e79a14.css +3 -0
- package/dist/server/.next/static/chunks/700389bfed628512.js +61 -0
- package/dist/server/.next/static/chunks/8d4c1c4e33fc41f3.js.map +1 -0
- package/dist/server/.next/static/chunks/{5e9dc9d078da6e2d.js.map → a898634af0862944.js.map} +1 -1
- package/dist/server/.next/static/chunks/{8d6bbd36cdf03018.js → d74cc70dd8ef74c9.js} +1 -1
- package/dist/server/.next/static/chunks/pages/_app.js +2 -2
- package/dist/server/.next/static/chunks/pages/_error.js +2 -2
- package/dist/server/.next/trace +1 -1
- package/package.json +3 -2
- package/dist/server/.next/server/chunks/[root-of-the-server]__ec0f2f72._.js +0 -3
- package/dist/server/.next/server/chunks/[root-of-the-server]__ec0f2f72._.js.map +0 -1
- package/dist/server/.next/server/chunks/ssr/_2488faea._.js.map +0 -1
- package/dist/server/.next/static/chunks/1f1c09f06b1f73d5.css +0 -3
- package/dist/server/.next/static/chunks/4791e420776e4b33.js.map +0 -1
- package/dist/server/.next/static/chunks/76692beeeb707278.css.map +0 -1
- package/dist/server/.next/static/chunks/f99d8b48dbb26003.js +0 -61
- /package/dist/server/.next/static/{DiL7txnLfsR2XvLBEz06H → CockuVPN955YqCV3kRDYs}/_buildManifest.js +0 -0
- /package/dist/server/.next/static/{DiL7txnLfsR2XvLBEz06H → CockuVPN955YqCV3kRDYs}/_clientMiddlewareManifest.json +0 -0
- /package/dist/server/.next/static/{DiL7txnLfsR2XvLBEz06H → CockuVPN955YqCV3kRDYs}/_ssgManifest.js +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["turbopack:///[project]/packages/server/src/lib/workspace-config.ts","turbopack:///[project]/packages/server/src/lib/workspace-types.ts","turbopack:///[project]/packages/server/src/lib/git-operations.ts","turbopack:///[project]/packages/server/src/lib/env-file-operations.ts","turbopack:///[project]/packages/server/src/lib/concurrent-controller.ts","turbopack:///[project]/packages/server/src/app/api/initialize-workspace/route.ts","turbopack:///[project]/node_modules/.pnpm/next@15.3.4_react-dom@19.1.0_react@19.1.0__react@19.1.0/node_modules/next/dist/src/build/templates/app-route.ts"],"sourcesContent":["import { readFile, writeFile, access, constants, rename } from 'fs/promises';\nimport type { ProjectsConfig } from './workspace-types';\nimport { PROJECT_CONFIG_PATH } from './workspace-types';\n\n/**\n * 读取并解析项目配置文件\n * @returns {Promise<ProjectsConfig>} 项目配置对象\n */\nexport async function getProjectsConfig(): Promise<ProjectsConfig> {\n try {\n await access(PROJECT_CONFIG_PATH, constants.F_OK);\n } catch {\n // 文件不存在,创建并写入空对象\n await saveProjectsConfig({});\n return {};\n }\n\n try {\n const configContent = await readFile(PROJECT_CONFIG_PATH, 'utf-8');\n // 如果文件为空,返回空对象\n if (!configContent) {\n return {};\n }\n return JSON.parse(configContent);\n } catch (error) {\n console.error('读取或解析项目配置文件失败:', error);\n // 在出错时返回空对象或抛出错误,这里选择抛出以通知调用者\n throw new Error('无法加载项目配置');\n }\n}\n\n/**\n * 将项目配置写入文件(原子操作)\n * @param {ProjectsConfig} config - 要保存的配置对象\n */\nexport async function saveProjectsConfig(config: ProjectsConfig): Promise<void> {\n const tempConfigPath = PROJECT_CONFIG_PATH + '.tmp';\n try {\n await writeFile(tempConfigPath, JSON.stringify(config, null, 2), 'utf-8');\n await rename(tempConfigPath, PROJECT_CONFIG_PATH);\n } catch (error) {\n console.error('保存项目配置文件失败:', error);\n throw new Error('无法保存项目配置');\n }\n}\n\n/**\n * 项目状态枚举\n */\nexport enum ProjectStatus {\n PENDING = 'pending',\n EXISTING = 'existing',\n CLONING = 'cloning',\n SUCCESS = 'success',\n FAILED = 'failed',\n RETRYING = 'retrying',\n}\n\n/**\n * 项目进度信息接口\n */\nexport interface ProjectProgress {\n projectName: string;\n status: ProjectStatus;\n progress: number; // 0-100\n message: string;\n error?: string;\n startTime?: number;\n endTime?: number;\n}\n\n/**\n * 初始化结果接口\n */\nexport interface InitializationResult {\n success: boolean;\n totalProjects: number;\n successCount: number;\n failedCount: number;\n failedProjects: string[];\n workspacePath: string;\n duration: number;\n}\n\n/**\n * Git 操作配置接口\n */\nexport interface GitOperationConfig {\n repoUrl: string;\n targetDir: string;\n timeout: number;\n onProgress?: (progress: number, message: string) => void;\n onError?: (error: string) => void;\n}","import { homedir, cpus } from 'os';\nimport { join } from 'path';\n\n/**\n * 工作空间配置常量\n */\nexport const WORKSPACE_CONFIG = {\n // 工作空间根目录路径\n WORKSPACE_ROOT: join(homedir(), 'Documents', 'prime-workspace'),\n\n // Git 操作超时时间 (毫秒)\n GIT_TIMEOUT: 300000, // 5分钟\n\n // 最大并发克隆数量(基于CPU核心数,最小2个,最大8个)\n MAX_CONCURRENT_CLONES: Math.max(2, Math.min(cpus().length, 8)),\n\n // 重试次数限制\n MAX_RETRY_ATTEMPTS: 3,\n} as const;\n\nexport const PROJECT_CONFIG_PATH = join(homedir(), '.prime-projects.json');\n\nexport interface ProjectConfig {\n repo: string;\n mockingIntercept?: boolean;\n mockOpen?: boolean;\n envs: {\n [envName: string]: {\n host: string;\n currentProxy: string;\n proxyEnv: {\n [key: string]: string;\n };\n envFileName: string;\n proxyKey: string;\n subApps?: string[];\n };\n };\n}\n\nexport interface ProjectsConfig {\n [projectName: string]: ProjectConfig;\n}\n\n/**\n * 项目状态枚举\n */\nexport enum ProjectStatus {\n PENDING = 'pending',\n EXISTING = 'existing',\n CLONING = 'cloning',\n SUCCESS = 'success',\n FAILED = 'failed',\n RETRYING = 'retrying',\n INCOMPLETE = 'incomplete', // 不完整的项目,需要清理\n}\n\n/**\n * 项目进度信息接口\n */\nexport interface ProjectProgress {\n projectName: string;\n status: ProjectStatus;\n progress: number; // 0-100\n message: string;\n error?: string;\n startTime?: number;\n endTime?: number;\n}\n\n/**\n * 初始化结果接口\n */\nexport interface InitializationResult {\n success: boolean;\n totalProjects: number;\n successCount: number;\n failedCount: number;\n failedProjects: string[];\n workspacePath: string;\n duration: number;\n}\n\n/**\n * Git 操作配置接口\n */\nexport interface GitOperationConfig {\n repoUrl: string;\n targetDir: string;\n timeout: number;\n onProgress?: (progress: number, message: string) => void;\n onError?: (error: string) => void;\n onLog?: (projectName: string, logType: 'stdout' | 'stderr' | 'progress', content: string) => void;\n} ","import { spawn, ChildProcess } from 'child_process';\nimport { existsSync, mkdirSync } from 'fs';\nimport { promises as fs } from 'fs';\nimport { join, basename } from 'path';\nimport {\n ProjectStatus,\n type GitOperationConfig,\n type ProjectProgress,\n} from './workspace-types';\n\n/**\n * 创建工作空间目录\n * @param workspacePath 工作空间路径\n * @returns 创建结果\n */\nexport async function createWorkspaceDirectory(workspacePath: string): Promise<{ success: boolean; error?: string }> {\n try {\n if (!existsSync(workspacePath)) {\n mkdirSync(workspacePath, { recursive: true });\n }\n return { success: true };\n } catch (error) {\n return { \n success: false, \n error: `创建工作空间目录失败: ${error instanceof Error ? error.message : String(error)}` \n };\n }\n}\n\n/**\n * 执行 Git 克隆操作\n * @param config Git 操作配置\n * @returns Promise<ProjectProgress>\n */\nexport async function cloneRepository(config: GitOperationConfig): Promise<ProjectProgress> {\n const { repoUrl, targetDir, timeout, onProgress, onError, onLog } = config;\n const projectName = basename(repoUrl, '.git');\n \n return new Promise<ProjectProgress>((resolve) => {\n const startTime = Date.now();\n \n // 更新开始状态\n const initialProgress: ProjectProgress = {\n projectName,\n status: ProjectStatus.CLONING,\n progress: 0,\n message: '开始克隆项目...',\n startTime,\n };\n onProgress?.(0, '开始克隆项目...');\n\n // 执行 git clone 命令\n const targetPath = join(targetDir, projectName);\n // 添加 --progress 参数来强制显示进度,--verbose 显示详细信息\n const gitArgs = ['clone', '--progress', '--verbose', repoUrl, targetPath];\n \n // 记录命令启动信息\n onLog?.(projectName, 'stdout', `[开始克隆] 执行命令: git ${gitArgs.join(' ')}\\n`);\n onLog?.(projectName, 'stdout', `[目标目录] ${targetPath}\\n`);\n onLog?.(projectName, 'stdout', `[仓库地址] ${repoUrl}\\n`);\n \n const gitProcess: ChildProcess = spawn('git', gitArgs, {\n cwd: targetDir,\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n let errorOutput = '';\n let progressValue = 0;\n \n // 记录进程启动成功\n onLog?.(projectName, 'stdout', `[进程启动] Git 进程 PID: ${gitProcess.pid}\\n`);\n\n // 设置超时\n const timeoutId = setTimeout(() => {\n onLog?.(projectName, 'stderr', `[超时警告] Git 进程运行超过 ${timeout / 1000}s,即将终止\\n`);\n gitProcess.kill('SIGTERM');\n \n const errorResult: ProjectProgress = {\n ...initialProgress,\n status: ProjectStatus.FAILED,\n progress: progressValue,\n message: '克隆操作超时',\n error: `克隆操作超时 (${timeout / 1000}s)`,\n endTime: Date.now(),\n };\n onLog?.(projectName, 'stderr', `[进程终止] 克隆操作超时\\n`);\n onError?.(`${projectName}: 克隆操作超时`);\n resolve(errorResult);\n }, timeout);\n\n // 处理标准输出\n gitProcess.stdout?.on('data', (data: Buffer) => {\n const stdoutText = data.toString();\n \n // 实时发送日志\n onLog?.(projectName, 'stdout', stdoutText);\n \n // 模拟进度更新(Git 克隆没有内置进度,这里基于时间估算)\n progressValue = Math.min(progressValue + 10, 80);\n onProgress?.(progressValue, '正在克隆代码...');\n });\n\n // 处理错误输出\n gitProcess.stderr?.on('data', (data: Buffer) => {\n const stderrText = data.toString();\n errorOutput += stderrText;\n \n // 判断是进度信息还是错误信息\n const isProgressInfo = stderrText.includes('remote:') || \n stderrText.includes('Receiving objects') || \n stderrText.includes('Resolving deltas') ||\n stderrText.includes('Counting objects') ||\n stderrText.includes('Enumerating objects') ||\n stderrText.includes('Compressing objects') ||\n stderrText.includes('upload-pack') ||\n stderrText.includes('POST git-') ||\n stderrText.includes('正克隆到') ||\n stderrText.includes('Cloning into');\n \n // 根据内容类型发送不同的日志\n if (isProgressInfo) {\n onLog?.(projectName, 'progress', stderrText);\n } else {\n onLog?.(projectName, 'stderr', stderrText);\n }\n \n // Git 的进度信息通常在 stderr 中\n if (stderrText.includes('Receiving objects') || stderrText.includes('Resolving deltas')) {\n progressValue = Math.min(progressValue + 5, 90);\n onProgress?.(progressValue, '正在接收对象...');\n } else if (stderrText.includes('Counting objects')) {\n progressValue = Math.min(progressValue + 2, 70);\n onProgress?.(progressValue, '正在计算对象...');\n } else if (stderrText.includes('Enumerating objects')) {\n progressValue = Math.min(progressValue + 2, 50);\n onProgress?.(progressValue, '正在枚举对象...');\n }\n });\n\n // 处理进程结束\n gitProcess.on('close', (code: number | null) => {\n clearTimeout(timeoutId);\n const endTime = Date.now();\n const duration = endTime - startTime;\n \n onLog?.(projectName, 'stdout', `[进程结束] Git 进程退出,代码: ${code},耗时: ${Math.round(duration / 1000)}s\\n`);\n \n if (code === 0) {\n // 克隆成功\n onLog?.(projectName, 'stdout', `[克隆成功] 项目已成功克隆到: ${targetPath}\\n`);\n const successResult: ProjectProgress = {\n ...initialProgress,\n status: ProjectStatus.SUCCESS,\n progress: 100,\n message: '克隆完成',\n endTime,\n };\n onProgress?.(100, '克隆完成');\n resolve(successResult);\n } else {\n // 克隆失败\n const parsedError = parseGitError(errorOutput);\n onLog?.(projectName, 'stderr', `[克隆失败] 错误信息: ${parsedError}\\n`);\n onLog?.(projectName, 'stderr', `[完整错误输出]\\n${errorOutput}\\n`);\n \n const failureResult: ProjectProgress = {\n ...initialProgress,\n status: ProjectStatus.FAILED,\n progress: progressValue,\n message: '克隆失败',\n error: parsedError || `Git 进程退出,代码: ${code}`,\n endTime,\n };\n onError?.(`${projectName}: ${failureResult.error}`);\n resolve(failureResult);\n }\n });\n\n // 处理进程错误\n gitProcess.on('error', (error: Error) => {\n clearTimeout(timeoutId);\n onLog?.(projectName, 'stderr', `[进程错误] Git 进程启动失败: ${error.message}\\n`);\n onLog?.(projectName, 'stderr', `[错误详情] ${error.stack || 'No stack trace'}\\n`);\n \n const errorResult: ProjectProgress = {\n ...initialProgress,\n status: ProjectStatus.FAILED,\n progress: progressValue,\n message: '进程启动失败',\n error: `进程启动失败: ${error.message}`,\n endTime: Date.now(),\n };\n onError?.(`${projectName}: ${error.message}`);\n resolve(errorResult);\n });\n });\n}\n\n/**\n * 解析 Git 错误信息,提供用户友好的错误描述\n * @param errorOutput Git stderr 输出\n * @returns 用户友好的错误描述\n */\nfunction parseGitError(errorOutput: string): string {\n const lowerOutput = errorOutput.toLowerCase();\n \n if (lowerOutput.includes('authentication failed') || lowerOutput.includes('access denied')) {\n return '身份验证失败,请检查仓库访问权限';\n }\n \n if (lowerOutput.includes('repository not found') || lowerOutput.includes('not found')) {\n return '仓库不存在或无法访问';\n }\n \n if (lowerOutput.includes('network') || lowerOutput.includes('connection')) {\n return '网络连接问题,请检查网络设置';\n }\n \n if (lowerOutput.includes('timeout')) {\n return '网络超时,请重试';\n }\n \n if (lowerOutput.includes('permission denied')) {\n return '权限被拒绝,请检查文件系统权限';\n }\n \n if (lowerOutput.includes('already exists')) {\n return '目标目录已存在';\n }\n \n // 返回原始错误的前200个字符\n return errorOutput.slice(0, 200) + (errorOutput.length > 200 ? '...' : '');\n}\n\n/**\n * 验证 Git 仓库 URL 格式\n * @param url Git 仓库 URL\n * @returns 是否有效\n */\nexport function isValidGitUrl(url: string): boolean {\n const gitUrlPattern = /^(https?:\\/\\/|git@)[^\\s]+\\.git$/i;\n return gitUrlPattern.test(url);\n}\n\n/**\n * 清理项目名称,移除不安全字符\n * @param projectName 项目名称\n * @returns 清理后的项目名称\n */\nexport function sanitizeProjectName(projectName: string): string {\n return projectName.replace(/[^a-zA-Z0-9\\-_]/g, '');\n}\n\n/**\n * 项目检查结果类型\n */\nexport type ProjectCheckResult = {\n exists: boolean;\n status: 'not_exists' | 'complete' | 'incomplete';\n needsCleanup: boolean;\n};\n\n/**\n * 检查项目状态(详细版本)\n * @param workspacePath 工作空间路径\n * @param projectName 项目名称\n * @returns Promise<ProjectCheckResult> 详细的项目状态\n */\nexport async function checkProjectStatus(workspacePath: string, projectName: string): Promise<ProjectCheckResult> {\n try {\n const projectPath = join(workspacePath, projectName);\n \n // 检查项目目录是否存在\n if (!existsSync(projectPath)) {\n return {\n exists: false,\n status: 'not_exists',\n needsCleanup: false\n };\n }\n \n // 检查是否为 Git 仓库(存在 .git 目录)\n const gitPath = join(projectPath, '.git');\n if (!existsSync(gitPath)) {\n return {\n exists: true,\n status: 'incomplete',\n needsCleanup: true\n };\n }\n \n // 更严格的完整性检查\n const isComplete = await isGitRepositoryComplete(projectPath);\n if (!isComplete) {\n console.log(`检测到不完整的Git仓库: ${projectPath}`);\n return {\n exists: true,\n status: 'incomplete',\n needsCleanup: true\n };\n }\n \n return {\n exists: true,\n status: 'complete',\n needsCleanup: false\n };\n } catch (error) {\n console.error(`检查项目 ${projectName} 状态时出错:`, error);\n return {\n exists: false,\n status: 'not_exists',\n needsCleanup: false\n };\n }\n}\n\n/**\n * 检查项目是否已存在于工作空间中(兼容版本)\n * @param workspacePath 工作空间路径\n * @param projectName 项目名称\n * @returns Promise<boolean> 项目是否存在且为有效的 Git 仓库\n */\nexport async function checkProjectExists(workspacePath: string, projectName: string): Promise<boolean> {\n const result = await checkProjectStatus(workspacePath, projectName);\n return result.status === 'complete';\n}\n\n/**\n * 检查Git仓库是否完整\n * @param projectPath 项目路径\n * @returns Promise<boolean> 仓库是否完整\n */\nasync function isGitRepositoryComplete(projectPath: string): Promise<boolean> {\n try {\n const gitPath = join(projectPath, '.git');\n \n // 检查关键的Git文件是否存在\n const requiredFiles = ['HEAD', 'config', 'refs'];\n for (const file of requiredFiles) {\n const filePath = join(gitPath, file);\n if (!existsSync(filePath)) {\n return false;\n }\n }\n \n // 检查是否有实际的项目文件(不只是.git目录)\n const entries = await fs.readdir(projectPath);\n const nonGitFiles = entries.filter((entry: string) => entry !== '.git');\n \n // 如果只有.git目录,说明克隆未完成\n if (nonGitFiles.length === 0) {\n return false;\n }\n \n // 检查HEAD文件是否有效\n const headPath = join(gitPath, 'HEAD');\n const headContent = await fs.readFile(headPath, 'utf-8');\n if (!headContent.trim() || headContent.includes('unborn')) {\n return false;\n }\n \n return true;\n } catch (error) {\n console.error('检查Git仓库完整性时出错:', error);\n return false;\n }\n}\n\n/**\n * 清理不完整的项目目录\n * @param projectPath 项目路径\n */\nexport async function cleanupIncompleteProject(projectPath: string): Promise<void> {\n try {\n console.log(`正在清理不完整的项目: ${projectPath}`);\n await fs.rm(projectPath, { recursive: true, force: true });\n console.log(`清理完成: ${projectPath}`);\n } catch (error) {\n console.error(`清理项目失败 ${projectPath}:`, error);\n // 清理失败不抛出错误,避免阻塞后续流程\n }\n}\n\n/**\n * 批量检查多个项目的存在状态\n * @param workspacePath 工作空间路径\n * @param projectNames 项目名称列表\n * @returns Promise<Record<string, boolean>> 项目名称到存在状态的映射\n */\nexport async function checkMultipleProjectsExist(\n workspacePath: string, \n projectNames: string[]\n): Promise<Record<string, boolean>> {\n const results: Record<string, boolean> = {};\n \n // 并行检查所有项目\n const checks = projectNames.map(async (projectName) => {\n const exists = await checkProjectExists(workspacePath, projectName);\n results[projectName] = exists;\n });\n \n await Promise.all(checks);\n return results;\n}\n\n/**\n * 在 Cursor 中打开项目\n * @param projectPath 项目的绝对路径\n * @returns Promise<{ success: boolean; error?: string }>\n */\nexport async function openProjectInCursor(projectPath: string): Promise<{ success: boolean; error?: string }> {\n return new Promise((resolve) => {\n // 验证项目路径存在\n if (!existsSync(projectPath)) {\n resolve({\n success: false,\n error: `项目路径不存在: ${projectPath}`\n });\n return;\n }\n\n // 执行 cursor 命令\n const cursorProcess = spawn('cursor', [projectPath], {\n stdio: ['ignore', 'pipe', 'pipe'],\n detached: true, // 让进程在后台独立运行\n env: {\n ...process.env,\n NODE_ENV: 'development', // 强制设置为开发模式\n }\n });\n\n let errorOutput = '';\n\n // 设置超时(10秒)\n const timeoutId = setTimeout(() => {\n cursorProcess.kill('SIGTERM');\n resolve({\n success: false,\n error: 'Cursor 命令执行超时'\n });\n }, 10000);\n\n // 处理错误输出\n cursorProcess.stderr?.on('data', (data: Buffer) => {\n errorOutput += data.toString();\n });\n\n // 处理进程退出\n cursorProcess.on('exit', (code: number | null) => {\n clearTimeout(timeoutId);\n \n if (code === 0) {\n resolve({ success: true });\n } else {\n resolve({\n success: false,\n error: `Cursor 退出代码: ${code}${errorOutput ? `, 错误: ${errorOutput}` : ''}`\n });\n }\n });\n\n // 处理进程错误(如命令不存在)\n cursorProcess.on('error', (error: Error) => {\n clearTimeout(timeoutId);\n \n if (error.message.includes('ENOENT')) {\n resolve({\n success: false,\n error: 'Cursor 命令未找到,请确保 Cursor CLI 已正确安装并在 PATH 中'\n });\n } else {\n resolve({\n success: false,\n error: `启动 Cursor 失败: ${error.message}`\n });\n }\n });\n\n // 让进程独立运行,不等待其完成\n cursorProcess.unref();\n });\n} ","import { promises as fs } from 'fs';\nimport { join } from 'path';\nimport type { ProjectConfig } from './workspace-types';\n\n/**\n * 为指定项目创建环境文件,如果文件已存在则跳过。\n * @param projectName - 项目名称\n * @param projectConfig - 项目配置\n * @param workspacePath - 工作空间根路径\n * @returns 一个包含已创建和已跳过文件列表的对象\n */\nexport async function createProjectEnvFiles(\n projectName: string,\n projectConfig: ProjectConfig,\n workspacePath: string,\n): Promise<{\n success: boolean;\n createdFiles: string[];\n skippedFiles: string[];\n error?: string;\n}> {\n const projectPath = join(workspacePath, projectName);\n const createdFiles: string[] = [];\n const skippedFiles: string[] = [];\n\n try {\n const envs = projectConfig.envs || {};\n for (const envName in envs) {\n const envConfig = envs[envName];\n if (envConfig.envFileName && envConfig.proxyKey) {\n const filePath = join(projectPath, envConfig.envFileName);\n \n try {\n await fs.access(filePath);\n // 文件已存在,跳过\n skippedFiles.push(envConfig.envFileName);\n } catch {\n // 文件不存在,创建它\n const currentProxyUrl = envConfig.proxyEnv[envConfig.currentProxy] || '';\n const content = `${envConfig.proxyKey}=${currentProxyUrl}`;\n await fs.writeFile(filePath, content, 'utf-8');\n createdFiles.push(envConfig.envFileName);\n }\n }\n }\n return { success: true, createdFiles, skippedFiles };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.error(`在为项目 ${projectName} 创建环境文件时出错:`, error);\n return { success: false, createdFiles, skippedFiles, error: errorMessage };\n }\n}\n\n/**\n * 为指定项目创建.mock文件夹\n * @param projectName - 项目名称\n * @param workspacePath - 工作空间根路径\n * @returns 创建结果\n */\nexport async function createProjectMockDirectories(\n projectName: string,\n workspacePath: string,\n): Promise<{\n success: boolean;\n createdDirectories: string[];\n skippedDirectories: string[];\n error?: string;\n}> {\n const projectPath = join(workspacePath, projectName);\n const mockPath = join(projectPath, '.mock');\n const createdDirectories: string[] = [];\n const skippedDirectories: string[] = [];\n\n try {\n // 创建 .mock 文件夹\n try {\n await fs.access(mockPath);\n skippedDirectories.push('.mock');\n } catch {\n await fs.mkdir(mockPath, { recursive: true });\n createdDirectories.push('.mock');\n }\n\n return { success: true, createdDirectories, skippedDirectories };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.error(`在为项目 ${projectName} 创建Mock目录时出错:`, error);\n return { success: false, createdDirectories, skippedDirectories, error: errorMessage };\n }\n}\n\n/**\n * 更新指定项目环境的环境文件内容\n * @param projectName - 项目名称\n * @param envName - 环境名称\n * @param projectConfig - 项目配置\n * @param workspacePath - 工作空间根路径\n * @returns 更新结果\n */\nexport async function updateProjectEnvFile(\n projectName: string,\n envName: string,\n projectConfig: ProjectConfig,\n workspacePath: string,\n): Promise<{\n success: boolean;\n updatedFile?: string;\n error?: string;\n}> {\n try {\n const envConfig = projectConfig.envs[envName];\n \n if (!envConfig) {\n return {\n success: false,\n error: `环境 ${envName} 不存在于项目 ${projectName} 配置中`,\n };\n }\n\n if (!envConfig.envFileName || !envConfig.proxyKey) {\n return {\n success: false,\n error: `环境 ${envName} 缺少 envFileName 或 proxyKey 配置`,\n };\n }\n\n const projectPath = join(workspacePath, projectName);\n const filePath = join(projectPath, envConfig.envFileName);\n \n // 获取当前代理URL\n const currentProxyUrl = envConfig.proxyEnv[envConfig.currentProxy] || envConfig.currentProxy;\n const content = `${envConfig.proxyKey}=${currentProxyUrl}`;\n \n // 写入文件内容\n await fs.writeFile(filePath, content, 'utf-8');\n \n console.log(`已更新环境文件: ${filePath}, 内容: ${content}`);\n \n return {\n success: true,\n updatedFile: envConfig.envFileName,\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.error(`更新项目 ${projectName} 环境 ${envName} 的环境文件时出错:`, error);\n return {\n success: false,\n error: errorMessage,\n };\n }\n} ","/**\n * 并发任务控制器\n * 用于控制异步任务的并发执行数量\n */\nexport class ConcurrentController {\n private running = new Set<Promise<unknown>>();\n private queue: Array<() => Promise<unknown>> = [];\n private readonly maxConcurrent: number;\n\n constructor(maxConcurrent: number) {\n this.maxConcurrent = maxConcurrent;\n }\n\n /**\n * 添加任务到执行队列\n * @param task 要执行的异步任务\n * @returns Promise<T> 任务结果\n */\n async add<T>(task: () => Promise<T>): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n this.queue.push(async () => {\n try {\n const result = await task();\n resolve(result);\n return result;\n } catch (error) {\n reject(error);\n throw error;\n }\n });\n \n this.process();\n });\n }\n\n /**\n * 处理任务队列\n */\n private async process(): Promise<void> {\n if (this.running.size >= this.maxConcurrent || this.queue.length === 0) {\n return;\n }\n\n const task = this.queue.shift();\n if (!task) return;\n\n const promise = task().finally(() => {\n this.running.delete(promise);\n this.process(); // 继续处理下一个任务\n });\n\n this.running.add(promise);\n }\n\n /**\n * 等待所有正在运行的任务完成\n */\n async waitForAll(): Promise<void> {\n while (this.running.size > 0 || this.queue.length > 0) {\n if (this.running.size > 0) {\n await Promise.race(this.running);\n }\n \n // 处理队列中剩余的任务\n this.process();\n }\n }\n\n /**\n * 获取当前状态信息\n */\n getStatus() {\n return {\n running: this.running.size,\n queued: this.queue.length,\n maxConcurrent: this.maxConcurrent\n };\n }\n} ","import {\n WORKSPACE_CONFIG,\n ProjectStatus,\n type InitializationResult,\n type ProjectConfig,\n type ProjectProgress,\n} from '@/lib/workspace-types';\nimport { getProjectsConfig } from '@/lib/workspace-config';\nimport {\n createWorkspaceDirectory,\n cloneRepository,\n checkMultipleProjectsExist,\n} from '@/lib/git-operations';\nimport { createProjectEnvFiles, createProjectMockDirectories } from '@/lib/env-file-operations';\nimport { ConcurrentController } from '@/lib/concurrent-controller';\n\n/**\n * 初始化工作空间 API 端点\n * 使用 Server-Sent Events 提供实时进度更新\n */\nexport async function GET() {\n const encoder = new TextEncoder();\n\n // 创建可读流用于 SSE\n const stream = new ReadableStream({\n async start(controller) {\n try {\n // 发送 SSE 消息的辅助函数\n const sendSSE = (data: Record<string, unknown>) => {\n // 对于 command_log 类型的消息,限制内容大小\n if (data.type === 'command_log' && typeof data.content === 'string') {\n const maxSize = 8 * 1024; // 8KB\n if (data.content.length > maxSize) {\n data.content = data.content.slice(0, maxSize) + '\\n[...日志内容已截断...]';\n }\n }\n \n const message = `data: ${JSON.stringify(data)}\\n\\n`;\n controller.enqueue(encoder.encode(message));\n };\n\n // 辅助函数:为项目创建环境文件和Mock目录结构\n const handleProjectSetup = async (\n projectName: string, \n config: ProjectConfig, \n progressBase = 25\n ) => {\n // 创建环境文件\n sendSSE({\n type: 'project_env_creation',\n projectName,\n message: `为项目 ${projectName} 检查/创建环境文件...`,\n progress: progressBase,\n });\n\n const envResult = await createProjectEnvFiles(projectName, config, workspacePath);\n\n if (envResult.success) {\n let message = `项目 ${projectName} 环境文件处理完成。`;\n if (envResult.createdFiles.length > 0) {\n message += ` 新建: ${envResult.createdFiles.join(', ')}.`;\n }\n if (envResult.skippedFiles.length > 0) {\n message += ` 已存在,跳过: ${envResult.skippedFiles.join(', ')}.`;\n }\n sendSSE({\n type: 'project_env_success',\n projectName,\n message,\n progress: progressBase + 2,\n });\n } else {\n sendSSE({\n type: 'project_env_failed',\n projectName,\n message: `为项目 ${projectName} 创建环境文件失败: ${envResult.error}`,\n error: envResult.error,\n progress: progressBase + 2,\n });\n return; // 环境文件创建失败,跳过Mock目录创建\n }\n\n // 创建Mock目录结构\n sendSSE({\n type: 'project_mock_creation',\n projectName,\n message: `为项目 ${projectName} 创建Mock目录结构...`,\n progress: progressBase + 3,\n });\n\n const mockResult = await createProjectMockDirectories(projectName, workspacePath);\n\n if (mockResult.success) {\n let message = `项目 ${projectName} Mock目录结构处理完成。`;\n if (mockResult.createdDirectories.length > 0) {\n message += ` 新建: ${mockResult.createdDirectories.join(', ')}.`;\n }\n if (mockResult.skippedDirectories.length > 0) {\n message += ` 已存在,跳过: ${mockResult.skippedDirectories.join(', ')}.`;\n }\n sendSSE({\n type: 'project_mock_success',\n projectName,\n message,\n progress: progressBase + 5,\n });\n } else {\n sendSSE({\n type: 'project_mock_failed',\n projectName,\n message: `为项目 ${projectName} 创建Mock目录失败: ${mockResult.error}`,\n error: mockResult.error,\n progress: progressBase + 5,\n });\n }\n };\n\n // 初始化状态\n sendSSE({ \n type: 'initialization', \n message: '开始初始化工作空间...',\n progress: 0 \n });\n\n // 创建工作空间目录\n const workspacePath = WORKSPACE_CONFIG.WORKSPACE_ROOT;\n const createResult = await createWorkspaceDirectory(workspacePath);\n \n if (!createResult.success) {\n sendSSE({ \n type: 'error', \n message: createResult.error,\n progress: 0 \n });\n controller.close();\n return;\n }\n\n sendSSE({ \n type: 'workspace_created', \n message: `工作空间已创建: ${workspacePath}`,\n progress: 10 \n });\n\n // 读取项目配置\n const projectsConfig = await getProjectsConfig();\n const projectEntries = Object.entries(projectsConfig);\n const totalProjects = projectEntries.length;\n\n if (totalProjects === 0) {\n sendSSE({ \n type: 'error', \n message: '没有找到需要克隆的项目',\n progress: 10 \n });\n controller.close();\n return;\n }\n\n sendSSE({ \n type: 'projects_loaded', \n message: `找到 ${totalProjects} 个项目准备克隆`,\n projects: projectEntries.map(([name]) => name),\n progress: 20 \n });\n\n // 初始化结果跟踪\n const result: InitializationResult = {\n success: true,\n totalProjects,\n successCount: 0,\n failedCount: 0,\n failedProjects: [],\n workspacePath,\n duration: 0,\n };\n\n const startTime = Date.now();\n\n // 检查哪些项目需要克隆\n const existenceMap = await checkMultipleProjectsExist(workspacePath, projectEntries.map(([name]) => name));\n const existingProjects = projectEntries.filter(([projectName]) => existenceMap[projectName]);\n const projectsToClone = projectEntries.filter(([projectName]) => !existenceMap[projectName]);\n \n // 为已存在的项目发送状态更新并创建环境文件\n for (const [projectName, config] of existingProjects) {\n sendSSE({ \n type: 'project_existing', \n projectName,\n message: `项目 ${projectName} 已存在,跳过克隆`,\n });\n await handleProjectSetup(projectName, config as ProjectConfig, 25);\n }\n \n // 更新结果统计,已存在项目计入成功计数\n result.successCount = existingProjects.length;\n \n if (projectsToClone.length === 0) {\n sendSSE({ \n type: 'completion', \n message: `所有 ${totalProjects} 个项目都已存在,无需克隆`,\n progress: 100,\n result: {\n success: true,\n totalProjects,\n successCount: totalProjects,\n failedCount: 0,\n failedProjects: [],\n workspacePath,\n duration: Date.now() - startTime,\n }\n });\n controller.close();\n return;\n }\n\n const concurrentClones = WORKSPACE_CONFIG.MAX_CONCURRENT_CLONES;\n \n sendSSE({ \n type: 'projects_filtered', \n message: `发现 ${existingProjects.length} 个项目已存在,${projectsToClone.length} 个项目需要克隆(并发数: ${concurrentClones})`,\n totalProjects,\n projectsToClone: projectsToClone.length,\n existingProjects: existingProjects.length,\n progress: 25 \n });\n\n // 创建并发控制器\n const concurrentController = new ConcurrentController(concurrentClones);\n \n // 跟踪项目克隆结果\n const cloneResults = new Map<string, {\n status: ProjectStatus;\n error?: string;\n result?: ProjectProgress;\n }>();\n\n // 并发克隆所有项目\n const cloneTasks = projectsToClone.map(([projectName, config], index) => {\n return concurrentController.add(async () => {\n const baseProgress = 25 + (index * 70) / (projectsToClone.length || 1);\n\n sendSSE({ \n type: 'project_start', \n projectName,\n message: `开始克隆项目: ${projectName} (${index + 1}/${projectsToClone.length})`,\n progress: Math.round(baseProgress) \n });\n\n try {\n const cloneResult = await cloneRepository({\n repoUrl: config.repo,\n targetDir: workspacePath,\n timeout: WORKSPACE_CONFIG.GIT_TIMEOUT,\n onProgress: (progress: number, message: string) => {\n const adjustedProgress = Math.round(baseProgress + (progress * 50) / ((projectsToClone.length || 1) * 100));\n sendSSE({ \n type: 'project_progress', \n projectName,\n progress: Math.min(adjustedProgress, 85),\n message \n });\n },\n onError: (error: string) => {\n sendSSE({ \n type: 'project_error', \n projectName,\n error,\n progress: Math.round(baseProgress + 50 / (projectsToClone.length || 1)) \n });\n },\n onLog: (logProjectName: string, logType: 'stdout' | 'stderr' | 'progress', content: string) => {\n sendSSE({\n type: 'command_log',\n projectName: logProjectName,\n logType,\n content,\n timestamp: Date.now(),\n });\n },\n });\n\n if (cloneResult.status === ProjectStatus.SUCCESS) {\n cloneResults.set(projectName, { status: ProjectStatus.SUCCESS, result: cloneResult });\n \n sendSSE({ \n type: 'project_success', \n projectName,\n message: `项目 ${projectName} 克隆成功`,\n progress: Math.round(baseProgress + 55 / (projectsToClone.length || 1)),\n result: cloneResult \n });\n\n // 创建环境文件和Mock目录\n await handleProjectSetup(\n projectName, \n config as ProjectConfig,\n Math.round(baseProgress + 60 / (projectsToClone.length || 1))\n );\n\n } else {\n cloneResults.set(projectName, { \n status: ProjectStatus.FAILED, \n error: cloneResult.error,\n result: cloneResult \n });\n \n sendSSE({ \n type: 'project_failed', \n projectName,\n message: `项目 ${projectName} 克隆失败: ${cloneResult.error}`,\n progress: Math.round(baseProgress + 70 / (projectsToClone.length || 1)),\n result: cloneResult \n });\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n cloneResults.set(projectName, { \n status: ProjectStatus.FAILED, \n error: errorMessage \n });\n \n sendSSE({ \n type: 'project_failed', \n projectName,\n message: `项目 ${projectName} 克隆异常: ${errorMessage}`,\n error: errorMessage,\n progress: Math.round(baseProgress + 70 / (projectsToClone.length || 1)) \n });\n }\n });\n });\n\n // 等待所有克隆任务完成\n await Promise.all(cloneTasks);\n \n // 统计结果\n for (const [projectName, cloneResult] of cloneResults) {\n if (cloneResult.status === ProjectStatus.SUCCESS) {\n result.successCount++;\n } else {\n result.failedCount++;\n result.failedProjects.push(projectName);\n }\n }\n\n // 完成总结\n result.duration = Date.now() - startTime;\n result.success = result.failedCount === 0;\n\n sendSSE({ \n type: 'completion', \n message: result.success \n ? `所有项目克隆完成!成功 ${result.successCount} 个,耗时 ${Math.round(result.duration / 1000)}s`\n : `克隆完成,部分失败。成功 ${result.successCount} 个,失败 ${result.failedCount} 个,耗时 ${Math.round(result.duration / 1000)}s`,\n progress: 100,\n result \n });\n\n controller.close();\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.error(\"工作空间初始化失败:\", error);\n \n const errorData = `data: ${JSON.stringify({ \n type: 'error', \n message: `工作空间初始化失败: ${errorMessage}`,\n error: errorMessage,\n progress: 0 \n })}\\n\\n`;\n \n controller.enqueue(encoder.encode(errorData));\n controller.close();\n }\n },\n });\n\n return new Response(stream, {\n headers: {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n 'Connection': 'keep-alive',\n 'Access-Control-Allow-Origin': '*',\n 'Access-Control-Allow-Headers': 'Cache-Control',\n },\n });\n}","import {\n AppRouteRouteModule,\n type AppRouteRouteModuleOptions,\n} from '../../server/route-modules/app-route/module.compiled'\nimport { RouteKind } from '../../server/route-kind'\nimport { patchFetch as _patchFetch } from '../../server/lib/patch-fetch'\n\nimport * as userland from 'VAR_USERLAND'\n\n// These are injected by the loader afterwards. This is injected as a variable\n// instead of a replacement because this could also be `undefined` instead of\n// an empty string.\ndeclare const nextConfigOutput: AppRouteRouteModuleOptions['nextConfigOutput']\n\n// We inject the nextConfigOutput here so that we can use them in the route\n// module.\n// INJECT:nextConfigOutput\n\nconst routeModule = new AppRouteRouteModule({\n definition: {\n kind: RouteKind.APP_ROUTE,\n page: 'VAR_DEFINITION_PAGE',\n pathname: 'VAR_DEFINITION_PATHNAME',\n filename: 'VAR_DEFINITION_FILENAME',\n bundlePath: 'VAR_DEFINITION_BUNDLE_PATH',\n },\n resolvedPagePath: 'VAR_RESOLVED_PAGE_PATH',\n nextConfigOutput,\n userland,\n})\n\n// Pull out the exports that we need to expose from the module. This should\n// be eliminated when we've moved the other routes to the new format. These\n// are used to hook into the route.\nconst { workAsyncStorage, workUnitAsyncStorage, serverHooks } = routeModule\n\nfunction patchFetch() {\n return _patchFetch({\n workAsyncStorage,\n workUnitAsyncStorage,\n })\n}\n\nexport {\n routeModule,\n workAsyncStorage,\n workUnitAsyncStorage,\n serverHooks,\n patchFetch,\n}\n"],"names":["AppRouteRouteModule","RouteKind","patchFetch","_patchFetch","userland","routeModule","definition","kind","APP_ROUTE","page","pathname","filename","bundlePath","resolvedPagePath","nextConfigOutput","workAsyncStorage","workUnitAsyncStorage","serverHooks"],"mappings":"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","ignoreList":[6]}
|
|
1
|
+
{"version":3,"sources":["turbopack:///[project]/packages/server/src/lib/workspace-config.ts","turbopack:///[project]/packages/server/src/lib/workspace-types.ts","turbopack:///[project]/packages/server/src/lib/git-operations.ts","turbopack:///[project]/packages/server/src/lib/env-file-operations.ts","turbopack:///[project]/packages/server/src/lib/concurrent-controller.ts","turbopack:///[project]/packages/server/src/app/api/initialize-workspace/route.ts","turbopack:///[project]/node_modules/.pnpm/next@15.3.4_react-dom@19.1.0_react@19.1.0__react@19.1.0/node_modules/next/dist/src/build/templates/app-route.ts"],"sourcesContent":["import { readFile, writeFile, access, constants, rename } from 'fs/promises';\nimport type { ProjectsConfig } from './workspace-types';\nimport { PROJECT_CONFIG_PATH } from './workspace-types';\n\n/**\n * 读取并解析项目配置文件\n * @returns {Promise<ProjectsConfig>} 项目配置对象\n */\nexport async function getProjectsConfig(): Promise<ProjectsConfig> {\n try {\n await access(PROJECT_CONFIG_PATH, constants.F_OK);\n } catch {\n // 文件不存在,创建并写入空对象\n await saveProjectsConfig({});\n return {};\n }\n\n try {\n const configContent = await readFile(PROJECT_CONFIG_PATH, 'utf-8');\n // 如果文件为空,返回空对象\n if (!configContent) {\n return {};\n }\n return JSON.parse(configContent);\n } catch (error) {\n console.error('读取或解析项目配置文件失败:', error);\n // 在出错时返回空对象或抛出错误,这里选择抛出以通知调用者\n throw new Error('无法加载项目配置');\n }\n}\n\n/**\n * 将项目配置写入文件(原子操作)\n * @param {ProjectsConfig} config - 要保存的配置对象\n */\nexport async function saveProjectsConfig(config: ProjectsConfig): Promise<void> {\n const tempConfigPath = PROJECT_CONFIG_PATH + '.tmp';\n try {\n await writeFile(tempConfigPath, JSON.stringify(config, null, 2), 'utf-8');\n await rename(tempConfigPath, PROJECT_CONFIG_PATH);\n } catch (error) {\n console.error('保存项目配置文件失败:', error);\n throw new Error('无法保存项目配置');\n }\n}\n\n/**\n * 项目状态枚举\n */\nexport enum ProjectStatus {\n PENDING = 'pending',\n EXISTING = 'existing',\n CLONING = 'cloning',\n SUCCESS = 'success',\n FAILED = 'failed',\n RETRYING = 'retrying',\n}\n\n/**\n * 项目进度信息接口\n */\nexport interface ProjectProgress {\n projectName: string;\n status: ProjectStatus;\n progress: number; // 0-100\n message: string;\n error?: string;\n startTime?: number;\n endTime?: number;\n}\n\n/**\n * 初始化结果接口\n */\nexport interface InitializationResult {\n success: boolean;\n totalProjects: number;\n successCount: number;\n failedCount: number;\n failedProjects: string[];\n workspacePath: string;\n duration: number;\n}\n\n/**\n * Git 操作配置接口\n */\nexport interface GitOperationConfig {\n repoUrl: string;\n targetDir: string;\n timeout: number;\n onProgress?: (progress: number, message: string) => void;\n onError?: (error: string) => void;\n}","import { homedir, cpus } from 'os';\nimport { join } from 'path';\n\n/**\n * 工作空间配置常量\n */\nexport const WORKSPACE_CONFIG = {\n // 工作空间根目录路径\n WORKSPACE_ROOT: join(homedir(), 'Documents', 'prime-workspace'),\n\n // Git 操作超时时间 (毫秒)\n GIT_TIMEOUT: 300000, // 5分钟\n\n // 最大并发克隆数量(基于CPU核心数,最小2个,最大8个)\n MAX_CONCURRENT_CLONES: Math.max(2, Math.min(cpus().length, 8)),\n\n // 重试次数限制\n MAX_RETRY_ATTEMPTS: 3,\n} as const;\n\nexport const PROJECT_CONFIG_PATH = join(homedir(), '.prime-projects.json');\n\nexport interface ProjectConfig {\n repo: string;\n mockingIntercept?: boolean;\n mockOpen?: boolean;\n envs: {\n [envName: string]: {\n host: string;\n currentProxy: string;\n proxyEnv: {\n [key: string]: string;\n };\n envFileName: string;\n proxyKey: string;\n subApps?: string[];\n };\n };\n}\n\nexport interface ProjectsConfig {\n [projectName: string]: ProjectConfig;\n}\n\n/**\n * 项目状态枚举\n */\nexport enum ProjectStatus {\n PENDING = 'pending',\n EXISTING = 'existing',\n CLONING = 'cloning',\n SUCCESS = 'success',\n FAILED = 'failed',\n RETRYING = 'retrying',\n INCOMPLETE = 'incomplete', // 不完整的项目,需要清理\n}\n\n/**\n * 项目进度信息接口\n */\nexport interface ProjectProgress {\n projectName: string;\n status: ProjectStatus;\n progress: number; // 0-100\n message: string;\n error?: string;\n startTime?: number;\n endTime?: number;\n}\n\n/**\n * 初始化结果接口\n */\nexport interface InitializationResult {\n success: boolean;\n totalProjects: number;\n successCount: number;\n failedCount: number;\n failedProjects: string[];\n workspacePath: string;\n duration: number;\n}\n\n/**\n * Git 操作配置接口\n */\nexport interface GitOperationConfig {\n repoUrl: string;\n targetDir: string;\n timeout: number;\n onProgress?: (progress: number, message: string) => void;\n onError?: (error: string) => void;\n onLog?: (projectName: string, logType: 'stdout' | 'stderr' | 'progress', content: string) => void;\n} ","import { spawn, ChildProcess } from 'child_process';\nimport { existsSync, mkdirSync } from 'fs';\nimport { promises as fs } from 'fs';\nimport { join, basename } from 'path';\nimport {\n ProjectStatus,\n type GitOperationConfig,\n type ProjectProgress,\n} from './workspace-types';\n\n/**\n * 创建工作空间目录\n * @param workspacePath 工作空间路径\n * @returns 创建结果\n */\nexport async function createWorkspaceDirectory(workspacePath: string): Promise<{ success: boolean; error?: string }> {\n try {\n if (!existsSync(workspacePath)) {\n mkdirSync(workspacePath, { recursive: true });\n }\n return { success: true };\n } catch (error) {\n return { \n success: false, \n error: `创建工作空间目录失败: ${error instanceof Error ? error.message : String(error)}` \n };\n }\n}\n\n/**\n * 执行 Git 克隆操作\n * @param config Git 操作配置\n * @returns Promise<ProjectProgress>\n */\nexport async function cloneRepository(config: GitOperationConfig): Promise<ProjectProgress> {\n const { repoUrl, targetDir, timeout, onProgress, onError, onLog } = config;\n const projectName = basename(repoUrl, '.git');\n \n return new Promise<ProjectProgress>((resolve) => {\n const startTime = Date.now();\n \n // 更新开始状态\n const initialProgress: ProjectProgress = {\n projectName,\n status: ProjectStatus.CLONING,\n progress: 0,\n message: '开始克隆项目...',\n startTime,\n };\n onProgress?.(0, '开始克隆项目...');\n\n // 执行 git clone 命令\n const targetPath = join(targetDir, projectName);\n // 添加 --progress 参数来强制显示进度,--verbose 显示详细信息\n const gitArgs = ['clone', '--progress', '--verbose', repoUrl, targetPath];\n \n // 记录命令启动信息\n onLog?.(projectName, 'stdout', `[开始克隆] 执行命令: git ${gitArgs.join(' ')}\\n`);\n onLog?.(projectName, 'stdout', `[目标目录] ${targetPath}\\n`);\n onLog?.(projectName, 'stdout', `[仓库地址] ${repoUrl}\\n`);\n \n const gitProcess: ChildProcess = spawn('git', gitArgs, {\n cwd: targetDir,\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n let errorOutput = '';\n let progressValue = 0;\n \n // 记录进程启动成功\n onLog?.(projectName, 'stdout', `[进程启动] Git 进程 PID: ${gitProcess.pid}\\n`);\n\n // 设置超时\n const timeoutId = setTimeout(() => {\n onLog?.(projectName, 'stderr', `[超时警告] Git 进程运行超过 ${timeout / 1000}s,即将终止\\n`);\n gitProcess.kill('SIGTERM');\n \n const errorResult: ProjectProgress = {\n ...initialProgress,\n status: ProjectStatus.FAILED,\n progress: progressValue,\n message: '克隆操作超时',\n error: `克隆操作超时 (${timeout / 1000}s)`,\n endTime: Date.now(),\n };\n onLog?.(projectName, 'stderr', `[进程终止] 克隆操作超时\\n`);\n onError?.(`${projectName}: 克隆操作超时`);\n resolve(errorResult);\n }, timeout);\n\n // 处理标准输出\n gitProcess.stdout?.on('data', (data: Buffer) => {\n const stdoutText = data.toString();\n \n // 实时发送日志\n onLog?.(projectName, 'stdout', stdoutText);\n \n // 模拟进度更新(Git 克隆没有内置进度,这里基于时间估算)\n progressValue = Math.min(progressValue + 10, 80);\n onProgress?.(progressValue, '正在克隆代码...');\n });\n\n // 处理错误输出\n gitProcess.stderr?.on('data', (data: Buffer) => {\n const stderrText = data.toString();\n errorOutput += stderrText;\n \n // 判断是进度信息还是错误信息\n const isProgressInfo = stderrText.includes('remote:') || \n stderrText.includes('Receiving objects') || \n stderrText.includes('Resolving deltas') ||\n stderrText.includes('Counting objects') ||\n stderrText.includes('Enumerating objects') ||\n stderrText.includes('Compressing objects') ||\n stderrText.includes('upload-pack') ||\n stderrText.includes('POST git-') ||\n stderrText.includes('正克隆到') ||\n stderrText.includes('Cloning into');\n \n // 根据内容类型发送不同的日志\n if (isProgressInfo) {\n onLog?.(projectName, 'progress', stderrText);\n } else {\n onLog?.(projectName, 'stderr', stderrText);\n }\n \n // Git 的进度信息通常在 stderr 中\n if (stderrText.includes('Receiving objects') || stderrText.includes('Resolving deltas')) {\n progressValue = Math.min(progressValue + 5, 90);\n onProgress?.(progressValue, '正在接收对象...');\n } else if (stderrText.includes('Counting objects')) {\n progressValue = Math.min(progressValue + 2, 70);\n onProgress?.(progressValue, '正在计算对象...');\n } else if (stderrText.includes('Enumerating objects')) {\n progressValue = Math.min(progressValue + 2, 50);\n onProgress?.(progressValue, '正在枚举对象...');\n }\n });\n\n // 处理进程结束\n gitProcess.on('close', (code: number | null) => {\n clearTimeout(timeoutId);\n const endTime = Date.now();\n const duration = endTime - startTime;\n \n onLog?.(projectName, 'stdout', `[进程结束] Git 进程退出,代码: ${code},耗时: ${Math.round(duration / 1000)}s\\n`);\n \n if (code === 0) {\n // 克隆成功\n onLog?.(projectName, 'stdout', `[克隆成功] 项目已成功克隆到: ${targetPath}\\n`);\n const successResult: ProjectProgress = {\n ...initialProgress,\n status: ProjectStatus.SUCCESS,\n progress: 100,\n message: '克隆完成',\n endTime,\n };\n onProgress?.(100, '克隆完成');\n resolve(successResult);\n } else {\n // 克隆失败\n const parsedError = parseGitError(errorOutput);\n onLog?.(projectName, 'stderr', `[克隆失败] 错误信息: ${parsedError}\\n`);\n onLog?.(projectName, 'stderr', `[完整错误输出]\\n${errorOutput}\\n`);\n \n const failureResult: ProjectProgress = {\n ...initialProgress,\n status: ProjectStatus.FAILED,\n progress: progressValue,\n message: '克隆失败',\n error: parsedError || `Git 进程退出,代码: ${code}`,\n endTime,\n };\n onError?.(`${projectName}: ${failureResult.error}`);\n resolve(failureResult);\n }\n });\n\n // 处理进程错误\n gitProcess.on('error', (error: Error) => {\n clearTimeout(timeoutId);\n onLog?.(projectName, 'stderr', `[进程错误] Git 进程启动失败: ${error.message}\\n`);\n onLog?.(projectName, 'stderr', `[错误详情] ${error.stack || 'No stack trace'}\\n`);\n \n const errorResult: ProjectProgress = {\n ...initialProgress,\n status: ProjectStatus.FAILED,\n progress: progressValue,\n message: '进程启动失败',\n error: `进程启动失败: ${error.message}`,\n endTime: Date.now(),\n };\n onError?.(`${projectName}: ${error.message}`);\n resolve(errorResult);\n });\n });\n}\n\n/**\n * 解析 Git 错误信息,提供用户友好的错误描述\n * @param errorOutput Git stderr 输出\n * @returns 用户友好的错误描述\n */\nfunction parseGitError(errorOutput: string): string {\n const lowerOutput = errorOutput.toLowerCase();\n \n if (lowerOutput.includes('authentication failed') || lowerOutput.includes('access denied')) {\n return '身份验证失败,请检查仓库访问权限';\n }\n \n if (lowerOutput.includes('repository not found') || lowerOutput.includes('not found')) {\n return '仓库不存在或无法访问';\n }\n \n if (lowerOutput.includes('network') || lowerOutput.includes('connection')) {\n return '网络连接问题,请检查网络设置';\n }\n \n if (lowerOutput.includes('timeout')) {\n return '网络超时,请重试';\n }\n \n if (lowerOutput.includes('permission denied')) {\n return '权限被拒绝,请检查文件系统权限';\n }\n \n if (lowerOutput.includes('already exists')) {\n return '目标目录已存在';\n }\n \n // 返回原始错误的前200个字符\n return errorOutput.slice(0, 200) + (errorOutput.length > 200 ? '...' : '');\n}\n\n/**\n * 验证 Git 仓库 URL 格式\n * @param url Git 仓库 URL\n * @returns 是否有效\n */\nexport function isValidGitUrl(url: string): boolean {\n const gitUrlPattern = /^(https?:\\/\\/|git@)[^\\s]+\\.git$/i;\n return gitUrlPattern.test(url);\n}\n\n/**\n * 清理项目名称,移除不安全字符\n * @param projectName 项目名称\n * @returns 清理后的项目名称\n */\nexport function sanitizeProjectName(projectName: string): string {\n return projectName.replace(/[^a-zA-Z0-9\\-_]/g, '');\n}\n\n/**\n * 项目检查结果类型\n */\nexport type ProjectCheckResult = {\n exists: boolean;\n status: 'not_exists' | 'complete' | 'incomplete';\n needsCleanup: boolean;\n};\n\n/**\n * 检查项目状态(详细版本)\n * @param workspacePath 工作空间路径\n * @param projectName 项目名称\n * @returns Promise<ProjectCheckResult> 详细的项目状态\n */\nexport async function checkProjectStatus(workspacePath: string, projectName: string): Promise<ProjectCheckResult> {\n try {\n const projectPath = join(workspacePath, projectName);\n \n // 检查项目目录是否存在\n if (!existsSync(projectPath)) {\n return {\n exists: false,\n status: 'not_exists',\n needsCleanup: false\n };\n }\n \n // 检查是否为 Git 仓库(存在 .git 目录)\n const gitPath = join(projectPath, '.git');\n if (!existsSync(gitPath)) {\n return {\n exists: true,\n status: 'incomplete',\n needsCleanup: true\n };\n }\n \n // 更严格的完整性检查\n const isComplete = await isGitRepositoryComplete(projectPath);\n if (!isComplete) {\n console.log(`检测到不完整的Git仓库: ${projectPath}`);\n return {\n exists: true,\n status: 'incomplete',\n needsCleanup: true\n };\n }\n \n return {\n exists: true,\n status: 'complete',\n needsCleanup: false\n };\n } catch (error) {\n console.error(`检查项目 ${projectName} 状态时出错:`, error);\n return {\n exists: false,\n status: 'not_exists',\n needsCleanup: false\n };\n }\n}\n\n/**\n * 检查项目是否已存在于工作空间中(兼容版本)\n * @param workspacePath 工作空间路径\n * @param projectName 项目名称\n * @returns Promise<boolean> 项目是否存在且为有效的 Git 仓库\n */\nexport async function checkProjectExists(workspacePath: string, projectName: string): Promise<boolean> {\n const result = await checkProjectStatus(workspacePath, projectName);\n return result.status === 'complete';\n}\n\n/**\n * 检查Git仓库是否完整\n * @param projectPath 项目路径\n * @returns Promise<boolean> 仓库是否完整\n */\nasync function isGitRepositoryComplete(projectPath: string): Promise<boolean> {\n try {\n const gitPath = join(projectPath, '.git');\n \n // 检查关键的Git文件是否存在\n const requiredFiles = ['HEAD', 'config', 'refs'];\n for (const file of requiredFiles) {\n const filePath = join(gitPath, file);\n if (!existsSync(filePath)) {\n return false;\n }\n }\n \n // 检查是否有实际的项目文件(不只是.git目录)\n const entries = await fs.readdir(projectPath);\n const nonGitFiles = entries.filter((entry: string) => entry !== '.git');\n \n // 如果只有.git目录,说明克隆未完成\n if (nonGitFiles.length === 0) {\n return false;\n }\n \n // 检查HEAD文件是否有效\n const headPath = join(gitPath, 'HEAD');\n const headContent = await fs.readFile(headPath, 'utf-8');\n if (!headContent.trim() || headContent.includes('unborn')) {\n return false;\n }\n \n return true;\n } catch (error) {\n console.error('检查Git仓库完整性时出错:', error);\n return false;\n }\n}\n\n/**\n * 清理不完整的项目目录\n * @param projectPath 项目路径\n */\nexport async function cleanupIncompleteProject(projectPath: string): Promise<void> {\n try {\n console.log(`正在清理不完整的项目: ${projectPath}`);\n await fs.rm(projectPath, { recursive: true, force: true });\n console.log(`清理完成: ${projectPath}`);\n } catch (error) {\n console.error(`清理项目失败 ${projectPath}:`, error);\n // 清理失败不抛出错误,避免阻塞后续流程\n }\n}\n\n/**\n * 批量检查多个项目的存在状态\n * @param workspacePath 工作空间路径\n * @param projectNames 项目名称列表\n * @returns Promise<Record<string, boolean>> 项目名称到存在状态的映射\n */\nexport async function checkMultipleProjectsExist(\n workspacePath: string, \n projectNames: string[]\n): Promise<Record<string, boolean>> {\n const results: Record<string, boolean> = {};\n \n // 并行检查所有项目\n const checks = projectNames.map(async (projectName) => {\n const exists = await checkProjectExists(workspacePath, projectName);\n results[projectName] = exists;\n });\n \n await Promise.all(checks);\n return results;\n}\n\n/**\n * 在 Cursor 中打开项目\n * @param projectPath 项目的绝对路径\n * @returns Promise<{ success: boolean; error?: string }>\n */\nexport async function openProjectInCursor(projectPath: string): Promise<{ success: boolean; error?: string }> {\n return new Promise((resolve) => {\n // 验证项目路径存在\n if (!existsSync(projectPath)) {\n resolve({\n success: false,\n error: `项目路径不存在: ${projectPath}`\n });\n return;\n }\n\n // 执行 cursor 命令\n const cursorProcess = spawn('cursor', [projectPath], {\n stdio: ['ignore', 'pipe', 'pipe'],\n detached: true, // 让进程在后台独立运行\n env: {\n ...process.env,\n NODE_ENV: 'development', // 强制设置为开发模式\n }\n });\n\n let errorOutput = '';\n\n // 设置超时(10秒)\n const timeoutId = setTimeout(() => {\n cursorProcess.kill('SIGTERM');\n resolve({\n success: false,\n error: 'Cursor 命令执行超时'\n });\n }, 10000);\n\n // 处理错误输出\n cursorProcess.stderr?.on('data', (data: Buffer) => {\n errorOutput += data.toString();\n });\n\n // 处理进程退出\n cursorProcess.on('exit', (code: number | null) => {\n clearTimeout(timeoutId);\n \n if (code === 0) {\n resolve({ success: true });\n } else {\n resolve({\n success: false,\n error: `Cursor 退出代码: ${code}${errorOutput ? `, 错误: ${errorOutput}` : ''}`\n });\n }\n });\n\n // 处理进程错误(如命令不存在)\n cursorProcess.on('error', (error: Error) => {\n clearTimeout(timeoutId);\n \n if (error.message.includes('ENOENT')) {\n resolve({\n success: false,\n error: 'Cursor 命令未找到,请确保 Cursor CLI 已正确安装并在 PATH 中'\n });\n } else {\n resolve({\n success: false,\n error: `启动 Cursor 失败: ${error.message}`\n });\n }\n });\n\n // 让进程独立运行,不等待其完成\n cursorProcess.unref();\n });\n} ","import { promises as fs } from 'fs';\nimport { join } from 'path';\nimport type { ProjectConfig } from './workspace-types';\n\n/**\n * 为指定项目创建环境文件,如果文件已存在则跳过。\n * @param projectName - 项目名称\n * @param projectConfig - 项目配置\n * @param workspacePath - 工作空间根路径\n * @returns 一个包含已创建和已跳过文件列表的对象\n */\nexport async function createProjectEnvFiles(\n projectName: string,\n projectConfig: ProjectConfig,\n workspacePath: string,\n): Promise<{\n success: boolean;\n createdFiles: string[];\n skippedFiles: string[];\n error?: string;\n}> {\n const projectPath = join(workspacePath, projectName);\n const createdFiles: string[] = [];\n const skippedFiles: string[] = [];\n\n try {\n const envs = projectConfig.envs || {};\n for (const envName in envs) {\n const envConfig = envs[envName];\n if (envConfig.envFileName && envConfig.proxyKey) {\n const filePath = join(projectPath, envConfig.envFileName);\n \n try {\n await fs.access(filePath);\n // 文件已存在,跳过\n skippedFiles.push(envConfig.envFileName);\n } catch {\n // 文件不存在,创建它\n const currentProxyUrl = envConfig.proxyEnv[envConfig.currentProxy] || '';\n const content = `${envConfig.proxyKey}=${currentProxyUrl}`;\n await fs.writeFile(filePath, content, 'utf-8');\n createdFiles.push(envConfig.envFileName);\n }\n }\n }\n return { success: true, createdFiles, skippedFiles };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.error(`在为项目 ${projectName} 创建环境文件时出错:`, error);\n return { success: false, createdFiles, skippedFiles, error: errorMessage };\n }\n}\n\n/**\n * 为指定项目创建.mock文件夹\n * @param projectName - 项目名称\n * @param workspacePath - 工作空间根路径\n * @returns 创建结果\n */\nexport async function createProjectMockDirectories(\n projectName: string,\n workspacePath: string,\n): Promise<{\n success: boolean;\n createdDirectories: string[];\n skippedDirectories: string[];\n error?: string;\n}> {\n const projectPath = join(workspacePath, projectName);\n const mockPath = join(projectPath, '.mock');\n const createdDirectories: string[] = [];\n const skippedDirectories: string[] = [];\n\n try {\n // 创建 .mock 文件夹\n try {\n await fs.access(mockPath);\n skippedDirectories.push('.mock');\n } catch {\n await fs.mkdir(mockPath, { recursive: true });\n createdDirectories.push('.mock');\n }\n\n return { success: true, createdDirectories, skippedDirectories };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.error(`在为项目 ${projectName} 创建Mock目录时出错:`, error);\n return { success: false, createdDirectories, skippedDirectories, error: errorMessage };\n }\n}\n\n/**\n * 更新指定项目环境的环境文件内容\n * @param projectName - 项目名称\n * @param envName - 环境名称\n * @param projectConfig - 项目配置\n * @param workspacePath - 工作空间根路径\n * @returns 更新结果\n */\nexport async function updateProjectEnvFile(\n projectName: string,\n envName: string,\n projectConfig: ProjectConfig,\n workspacePath: string,\n): Promise<{\n success: boolean;\n updatedFile?: string;\n error?: string;\n}> {\n try {\n const envConfig = projectConfig.envs[envName];\n \n if (!envConfig) {\n return {\n success: false,\n error: `环境 ${envName} 不存在于项目 ${projectName} 配置中`,\n };\n }\n\n if (!envConfig.envFileName || !envConfig.proxyKey) {\n return {\n success: false,\n error: `环境 ${envName} 缺少 envFileName 或 proxyKey 配置`,\n };\n }\n\n const projectPath = join(workspacePath, projectName);\n const filePath = join(projectPath, envConfig.envFileName);\n \n // 获取当前代理URL\n const currentProxyUrl = envConfig.proxyEnv[envConfig.currentProxy] || envConfig.currentProxy;\n const content = `${envConfig.proxyKey}=${currentProxyUrl}`;\n \n // 写入文件内容\n await fs.writeFile(filePath, content, 'utf-8');\n \n console.log(`已更新环境文件: ${filePath}, 内容: ${content}`);\n \n return {\n success: true,\n updatedFile: envConfig.envFileName,\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.error(`更新项目 ${projectName} 环境 ${envName} 的环境文件时出错:`, error);\n return {\n success: false,\n error: errorMessage,\n };\n }\n} ","/**\n * 并发任务控制器\n * 用于控制异步任务的并发执行数量\n */\nexport class ConcurrentController {\n private running = new Set<Promise<unknown>>();\n private queue: Array<() => Promise<unknown>> = [];\n private readonly maxConcurrent: number;\n\n constructor(maxConcurrent: number) {\n this.maxConcurrent = maxConcurrent;\n }\n\n /**\n * 添加任务到执行队列\n * @param task 要执行的异步任务\n * @returns Promise<T> 任务结果\n */\n async add<T>(task: () => Promise<T>): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n this.queue.push(async () => {\n try {\n const result = await task();\n resolve(result);\n return result;\n } catch (error) {\n reject(error);\n throw error;\n }\n });\n \n this.process();\n });\n }\n\n /**\n * 处理任务队列\n */\n private async process(): Promise<void> {\n if (this.running.size >= this.maxConcurrent || this.queue.length === 0) {\n return;\n }\n\n const task = this.queue.shift();\n if (!task) return;\n\n const promise = task().finally(() => {\n this.running.delete(promise);\n this.process(); // 继续处理下一个任务\n });\n\n this.running.add(promise);\n }\n\n /**\n * 等待所有正在运行的任务完成\n */\n async waitForAll(): Promise<void> {\n while (this.running.size > 0 || this.queue.length > 0) {\n if (this.running.size > 0) {\n await Promise.race(this.running);\n }\n \n // 处理队列中剩余的任务\n this.process();\n }\n }\n\n /**\n * 获取当前状态信息\n */\n getStatus() {\n return {\n running: this.running.size,\n queued: this.queue.length,\n maxConcurrent: this.maxConcurrent\n };\n }\n} ","import {\n WORKSPACE_CONFIG,\n ProjectStatus,\n type InitializationResult,\n type ProjectConfig,\n type ProjectProgress,\n} from '@/lib/workspace-types';\nimport { getProjectsConfig } from '@/lib/workspace-config';\nimport {\n createWorkspaceDirectory,\n cloneRepository,\n checkMultipleProjectsExist,\n} from '@/lib/git-operations';\nimport { createProjectEnvFiles, createProjectMockDirectories } from '@/lib/env-file-operations';\nimport { ConcurrentController } from '@/lib/concurrent-controller';\n\n/**\n * 初始化工作空间 API 端点\n * 使用 Server-Sent Events 提供实时进度更新\n */\nexport async function GET() {\n const encoder = new TextEncoder();\n\n // 创建可读流用于 SSE\n const stream = new ReadableStream({\n async start(controller) {\n try {\n // 发送 SSE 消息的辅助函数\n const sendSSE = (data: Record<string, unknown>) => {\n // 对于 command_log 类型的消息,限制内容大小\n if (data.type === 'command_log' && typeof data.content === 'string') {\n const maxSize = 8 * 1024; // 8KB\n if (data.content.length > maxSize) {\n data.content = data.content.slice(0, maxSize) + '\\n[...日志内容已截断...]';\n }\n }\n \n const message = `data: ${JSON.stringify(data)}\\n\\n`;\n controller.enqueue(encoder.encode(message));\n };\n\n // 辅助函数:为项目创建环境文件和Mock目录结构\n const handleProjectSetup = async (\n projectName: string, \n config: ProjectConfig, \n progressBase = 25\n ) => {\n // 创建环境文件\n sendSSE({\n type: 'project_env_creation',\n projectName,\n message: `为项目 ${projectName} 检查/创建环境文件...`,\n progress: progressBase,\n });\n\n const envResult = await createProjectEnvFiles(projectName, config, workspacePath);\n\n if (envResult.success) {\n let message = `项目 ${projectName} 环境文件处理完成。`;\n if (envResult.createdFiles.length > 0) {\n message += ` 新建: ${envResult.createdFiles.join(', ')}.`;\n }\n if (envResult.skippedFiles.length > 0) {\n message += ` 已存在,跳过: ${envResult.skippedFiles.join(', ')}.`;\n }\n sendSSE({\n type: 'project_env_success',\n projectName,\n message,\n progress: progressBase + 2,\n });\n } else {\n sendSSE({\n type: 'project_env_failed',\n projectName,\n message: `为项目 ${projectName} 创建环境文件失败: ${envResult.error}`,\n error: envResult.error,\n progress: progressBase + 2,\n });\n return; // 环境文件创建失败,跳过Mock目录创建\n }\n\n // 创建Mock目录结构\n sendSSE({\n type: 'project_mock_creation',\n projectName,\n message: `为项目 ${projectName} 创建Mock目录结构...`,\n progress: progressBase + 3,\n });\n\n const mockResult = await createProjectMockDirectories(projectName, workspacePath);\n\n if (mockResult.success) {\n let message = `项目 ${projectName} Mock目录结构处理完成。`;\n if (mockResult.createdDirectories.length > 0) {\n message += ` 新建: ${mockResult.createdDirectories.join(', ')}.`;\n }\n if (mockResult.skippedDirectories.length > 0) {\n message += ` 已存在,跳过: ${mockResult.skippedDirectories.join(', ')}.`;\n }\n sendSSE({\n type: 'project_mock_success',\n projectName,\n message,\n progress: progressBase + 5,\n });\n } else {\n sendSSE({\n type: 'project_mock_failed',\n projectName,\n message: `为项目 ${projectName} 创建Mock目录失败: ${mockResult.error}`,\n error: mockResult.error,\n progress: progressBase + 5,\n });\n }\n };\n\n // 初始化状态\n sendSSE({ \n type: 'initialization', \n message: '开始初始化工作空间...',\n progress: 0 \n });\n\n // 创建工作空间目录\n const workspacePath = WORKSPACE_CONFIG.WORKSPACE_ROOT;\n const createResult = await createWorkspaceDirectory(workspacePath);\n \n if (!createResult.success) {\n sendSSE({ \n type: 'error', \n message: createResult.error,\n progress: 0 \n });\n controller.close();\n return;\n }\n\n sendSSE({ \n type: 'workspace_created', \n message: `工作空间已创建: ${workspacePath}`,\n progress: 10 \n });\n\n // 读取项目配置\n const projectsConfig = await getProjectsConfig();\n const projectEntries = Object.entries(projectsConfig);\n const totalProjects = projectEntries.length;\n\n if (totalProjects === 0) {\n sendSSE({ \n type: 'error', \n message: '没有找到需要克隆的项目',\n progress: 10 \n });\n controller.close();\n return;\n }\n\n sendSSE({ \n type: 'projects_loaded', \n message: `找到 ${totalProjects} 个项目准备克隆`,\n projects: projectEntries.map(([name]) => name),\n progress: 20 \n });\n\n // 初始化结果跟踪\n const result: InitializationResult = {\n success: true,\n totalProjects,\n successCount: 0,\n failedCount: 0,\n failedProjects: [],\n workspacePath,\n duration: 0,\n };\n\n const startTime = Date.now();\n\n // 检查哪些项目需要克隆\n const existenceMap = await checkMultipleProjectsExist(workspacePath, projectEntries.map(([name]) => name));\n const existingProjects = projectEntries.filter(([projectName]) => existenceMap[projectName]);\n const projectsToClone = projectEntries.filter(([projectName]) => !existenceMap[projectName]);\n \n // 为已存在的项目发送状态更新并创建环境文件\n for (const [projectName, config] of existingProjects) {\n sendSSE({ \n type: 'project_existing', \n projectName,\n message: `项目 ${projectName} 已存在,跳过克隆`,\n });\n await handleProjectSetup(projectName, config as ProjectConfig, 25);\n }\n \n // 更新结果统计,已存在项目计入成功计数\n result.successCount = existingProjects.length;\n \n if (projectsToClone.length === 0) {\n sendSSE({ \n type: 'completion', \n message: `所有 ${totalProjects} 个项目都已存在,无需克隆`,\n progress: 100,\n result: {\n success: true,\n totalProjects,\n successCount: totalProjects,\n failedCount: 0,\n failedProjects: [],\n workspacePath,\n duration: Date.now() - startTime,\n }\n });\n controller.close();\n return;\n }\n\n const concurrentClones = WORKSPACE_CONFIG.MAX_CONCURRENT_CLONES;\n \n sendSSE({ \n type: 'projects_filtered', \n message: `发现 ${existingProjects.length} 个项目已存在,${projectsToClone.length} 个项目需要克隆(并发数: ${concurrentClones})`,\n totalProjects,\n projectsToClone: projectsToClone.length,\n existingProjects: existingProjects.length,\n progress: 25 \n });\n\n // 创建并发控制器\n const concurrentController = new ConcurrentController(concurrentClones);\n \n // 跟踪项目克隆结果\n const cloneResults = new Map<string, {\n status: ProjectStatus;\n error?: string;\n result?: ProjectProgress;\n }>();\n\n // 并发克隆所有项目\n const cloneTasks = projectsToClone.map(([projectName, config], index) => {\n return concurrentController.add(async () => {\n const baseProgress = 25 + (index * 70) / (projectsToClone.length || 1);\n\n sendSSE({ \n type: 'project_start', \n projectName,\n message: `开始克隆项目: ${projectName} (${index + 1}/${projectsToClone.length})`,\n progress: Math.round(baseProgress) \n });\n\n try {\n const cloneResult = await cloneRepository({\n repoUrl: config.repo,\n targetDir: workspacePath,\n timeout: WORKSPACE_CONFIG.GIT_TIMEOUT,\n onProgress: (progress: number, message: string) => {\n const adjustedProgress = Math.round(baseProgress + (progress * 50) / ((projectsToClone.length || 1) * 100));\n sendSSE({ \n type: 'project_progress', \n projectName,\n progress: Math.min(adjustedProgress, 85),\n message \n });\n },\n onError: (error: string) => {\n sendSSE({ \n type: 'project_error', \n projectName,\n error,\n progress: Math.round(baseProgress + 50 / (projectsToClone.length || 1)) \n });\n },\n onLog: (logProjectName: string, logType: 'stdout' | 'stderr' | 'progress', content: string) => {\n sendSSE({\n type: 'command_log',\n projectName: logProjectName,\n logType,\n content,\n timestamp: Date.now(),\n });\n },\n });\n\n if (cloneResult.status === ProjectStatus.SUCCESS) {\n cloneResults.set(projectName, { status: ProjectStatus.SUCCESS, result: cloneResult });\n \n sendSSE({ \n type: 'project_success', \n projectName,\n message: `项目 ${projectName} 克隆成功`,\n progress: Math.round(baseProgress + 55 / (projectsToClone.length || 1)),\n result: cloneResult \n });\n\n // 创建环境文件和Mock目录\n await handleProjectSetup(\n projectName, \n config as ProjectConfig,\n Math.round(baseProgress + 60 / (projectsToClone.length || 1))\n );\n\n } else {\n cloneResults.set(projectName, { \n status: ProjectStatus.FAILED, \n error: cloneResult.error,\n result: cloneResult \n });\n \n sendSSE({ \n type: 'project_failed', \n projectName,\n message: `项目 ${projectName} 克隆失败: ${cloneResult.error}`,\n progress: Math.round(baseProgress + 70 / (projectsToClone.length || 1)),\n result: cloneResult \n });\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n cloneResults.set(projectName, { \n status: ProjectStatus.FAILED, \n error: errorMessage \n });\n \n sendSSE({ \n type: 'project_failed', \n projectName,\n message: `项目 ${projectName} 克隆异常: ${errorMessage}`,\n error: errorMessage,\n progress: Math.round(baseProgress + 70 / (projectsToClone.length || 1)) \n });\n }\n });\n });\n\n // 等待所有克隆任务完成\n await Promise.all(cloneTasks);\n \n // 统计结果\n for (const [projectName, cloneResult] of cloneResults) {\n if (cloneResult.status === ProjectStatus.SUCCESS) {\n result.successCount++;\n } else {\n result.failedCount++;\n result.failedProjects.push(projectName);\n }\n }\n\n // 完成总结\n result.duration = Date.now() - startTime;\n result.success = result.failedCount === 0;\n\n sendSSE({ \n type: 'completion', \n message: result.success \n ? `所有项目克隆完成!成功 ${result.successCount} 个,耗时 ${Math.round(result.duration / 1000)}s`\n : `克隆完成,部分失败。成功 ${result.successCount} 个,失败 ${result.failedCount} 个,耗时 ${Math.round(result.duration / 1000)}s`,\n progress: 100,\n result \n });\n\n controller.close();\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.error(\"工作空间初始化失败:\", error);\n \n const errorData = `data: ${JSON.stringify({ \n type: 'error', \n message: `工作空间初始化失败: ${errorMessage}`,\n error: errorMessage,\n progress: 0 \n })}\\n\\n`;\n \n controller.enqueue(encoder.encode(errorData));\n controller.close();\n }\n },\n });\n\n return new Response(stream, {\n headers: {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n 'Connection': 'keep-alive',\n 'Access-Control-Allow-Origin': '*',\n 'Access-Control-Allow-Headers': 'Cache-Control',\n },\n });\n}","import {\n AppRouteRouteModule,\n type AppRouteRouteModuleOptions,\n} from '../../server/route-modules/app-route/module.compiled'\nimport { RouteKind } from '../../server/route-kind'\nimport { patchFetch as _patchFetch } from '../../server/lib/patch-fetch'\n\nimport * as userland from 'VAR_USERLAND'\n\n// These are injected by the loader afterwards. This is injected as a variable\n// instead of a replacement because this could also be `undefined` instead of\n// an empty string.\ndeclare const nextConfigOutput: AppRouteRouteModuleOptions['nextConfigOutput']\n\n// We inject the nextConfigOutput here so that we can use them in the route\n// module.\n// INJECT:nextConfigOutput\n\nconst routeModule = new AppRouteRouteModule({\n definition: {\n kind: RouteKind.APP_ROUTE,\n page: 'VAR_DEFINITION_PAGE',\n pathname: 'VAR_DEFINITION_PATHNAME',\n filename: 'VAR_DEFINITION_FILENAME',\n bundlePath: 'VAR_DEFINITION_BUNDLE_PATH',\n },\n resolvedPagePath: 'VAR_RESOLVED_PAGE_PATH',\n nextConfigOutput,\n userland,\n})\n\n// Pull out the exports that we need to expose from the module. This should\n// be eliminated when we've moved the other routes to the new format. These\n// are used to hook into the route.\nconst { workAsyncStorage, workUnitAsyncStorage, serverHooks } = routeModule\n\nfunction patchFetch() {\n return _patchFetch({\n workAsyncStorage,\n workUnitAsyncStorage,\n })\n}\n\nexport {\n routeModule,\n workAsyncStorage,\n workUnitAsyncStorage,\n serverHooks,\n patchFetch,\n}\n"],"names":["AppRouteRouteModule","RouteKind","patchFetch","_patchFetch","userland","routeModule","definition","kind","APP_ROUTE","page","pathname","filename","bundlePath","resolvedPagePath","nextConfigOutput","workAsyncStorage","workUnitAsyncStorage","serverHooks"],"mappings":"0IAAA,IAAA,EAAA,EAAA,CAAA,CAAA,MAEA,EAAA,EAAA,CAAA,CAAA,OAMO,eAAe,IACpB,GAAI,CACF,MAAM,CAAA,EAAA,EAAA,MAAA,AAAK,EAAE,EAAA,mBAAmB,CAAE,EAAA,GAA5B,MAAqC,CAAC,IAA/B,AAAmC,CAClD,CAAE,KAAM,CAGN,OADA,MAHkC,AAG5B,EAAmB,CAAC,GACnB,CAAC,CACV,CAEA,GAAI,CACF,IAAM,EAAgB,MAAM,CAAA,EAAA,EAAA,QAAA,AAAO,EAAE,EAAA,mBAAmB,CAAE,GAA9B,MAE5B,GAAI,CAAC,EACH,CAHmC,KAG5B,CAAC,EAEV,IAHoB,GAGb,KAAK,KAAK,CAAC,EACpB,CAAE,MAAO,EAAO,CAGd,MAFA,QAAQ,KAAK,CAAC,iBAAkB,GAE1B,AAAI,MAAM,WAClB,CACF,CAMO,eAAe,EAAmB,CAAsB,EAC7D,IAAM,EAAiB,EAAA,mBAAmB,CAAG,OAC7C,GAAI,CACF,KAFqB,CAEf,CAAA,EAAA,EAAA,SAAA,AAAQ,EAAE,EAAgB,KAAK,SAAS,CAAC,EAAQ,KAAjD,AAAuD,GAAI,SACjE,MAAM,CAAA,EAAA,EAAA,MAAA,AAAK,EAAE,EAAgB,EAAA,mBAAmB,CAClD,CAAE,EADM,IACC,EAAO,CAEd,MAH6B,AAE7B,QAAQ,KAAK,CAAC,cAAe,GACvB,AAAI,MAAM,WAClB,CACF,CAKO,IAAK,EAAA,SAAA,CAAA,mIAAA,6wCCjDZ,IAAA,EAAA,EAAA,CAAA,CAAA,OACA,EAAA,EAAA,CAAA,CAAA,OAKO,IAAM,EAAmB,CAE9B,eAAgB,CAAA,EAAA,EAAA,IAAA,AAAG,EAAE,CAAA,EAAA,EAAA,OAAA,AAAM,IAAK,YAAa,EAA7B,WAAK,MAGrB,YAAa,IAGb,sBAAuB,KAAK,GAAG,CAAC,EAAG,KAAK,GAAG,CAAC,CAAA,EAAA,EAAA,IAAA,AAAG,IAAI,MAAM,CAAE,IAG3D,iBAH4C,EAGxB,CACtB,EAEa,EAAsB,CAAA,EAAA,EAAA,IAAA,AAAG,EAAE,CAAA,EAAA,EAAA,OAAA,AAAM,IAAK,cAAhB,UA2B5B,CA3BiC,GA2B5B,EAAA,SAAA,CAAA,6JAAA,4lBC/CZ,IAAA,EAAA,EAAA,CAAA,CAAA,OACA,EAAA,EAAA,CAAA,CAAA,OAEA,EAAA,EAAA,CAAA,CAAA,OACA,EAAA,EAAA,CAAA,CAAA,OAWO,eAAe,EAAyB,CAAqB,EAClE,GAAI,CAIF,MAHI,AAAC,CAAA,EAAA,EAAA,UAAA,AAAS,EAAE,IACd,CAAA,EAAA,EAAA,OAD8B,EAC9B,AAAQ,EAAE,EAAe,CAAE,CADxB,UACmC,CAAK,GAEtC,CAAE,MAFP,GAEgB,CAAK,CACzB,CAAE,MAAO,EAAO,CACd,MAAO,CACL,SAAS,EACT,MAAO,CAAC,YAAY,EAAE,aAAiB,MAAQ,EAAM,OAAO,CAAG,OAAO,GAAA,CAAQ,AAChF,CACF,CACF,CAOO,eAAe,EAAgB,CAA0B,EAC9D,GAAM,SAAE,CAAO,WAAE,CAAS,SAAE,CAAO,YAAE,CAAU,SAAE,CAAO,OAAE,CAAK,CAAE,CAAG,EAC9D,EAAc,CAAA,EAAA,EAAA,QAAO,AAAP,EAAS,EAAS,QAEtC,OAAO,IAAI,KAFS,GAEgB,AAAC,IACnC,IAAM,EAAY,KAAK,GAAG,GAGpB,EAAmC,aACvC,EACA,OAAQ,EAAA,aAAa,CAAC,OAAO,CAC7B,SAAU,EACV,GAFQ,KAEC,sBACT,CACF,EACA,IAAa,EAAG,aAGhB,IAAM,EAAa,GAAA,EAAA,IAAA,AAAG,EAAE,EAAW,GAE7B,EAAU,CAAC,QAAS,aAAc,CAFrB,WAEkC,EAAS,EAAW,CAGzE,IAAQ,EAAa,SAAU,CAAC,iBAAiB,EAAE,EAAQ,IAAI,CAAC,KAAK;AAAE,CAAC,EACxE,IAAQ,EAAa,SAAU,CAAC,OAAO,EAAE,WAAW;AAAE,CAAC,EACvD,IAAQ,EAAa,SAAU,CAAC,OAAO,EAAE,QAAQ;AAAE,CAAC,EAEpD,IAAM,EAA2B,CAAA,EAAA,EAAA,KAAA,AAAI,EAAE,MAAO,EAAS,CACrD,IAAK,EACL,MAAO,CAAC,OAFuB,AAEf,OAAQ,OAAO,AACjC,GAEI,EAAc,GACd,EAAgB,EAGpB,IAAQ,EAAa,SAAU,CAAC,mBAAmB,EAAE,EAAW,GAAG,CAAC;AAAE,CAAC,EAGvE,IAAM,EAAY,WAAW,KAC3B,IAAQ,EAAa,SAAU,CAAC,kBAAkB,EAAE,EAAU,IAAK;AAAQ,CAAC,EAC5E,EAAW,IAAI,CAAC,WAEhB,IAAM,EAA+B,CACnC,GAAG,CAAe,CAClB,OAAQ,EAAA,aAAa,CAAC,MAAM,CAC5B,SAAU,EACV,IAFQ,IAEC,SACT,MAAO,CAAC,QAAQ,EAAE,EAAU,IAAK,EAAE,CAAC,CACpC,QAAS,KAAK,GAAG,EACnB,EACA,IAAQ,EAAa,SAAU,CAAC;AAAe,CAAC,EAChD,IAAU,CAAA,EAAG,EAAY,QAAQ,CAAC,EAClC,EAAQ,EACV,EAAG,GAGH,EAAW,MAAM,EAAE,GAAG,OAAQ,AAAC,IAC7B,IAAM,EAAa,EAAK,QAAQ,GAGhC,IAAQ,EAAa,SAAU,GAG/B,EAAgB,KAAK,GAAG,CAAC,EAAgB,GAAI,IAC7C,IAAa,EAAe,YAC9B,GAGA,EAAW,MAAM,EAAE,GAAG,OAAQ,AAAC,IAC7B,IAAM,EAAa,EAAK,QAAQ,GAChC,GAAe,EAGQ,EAAW,QAAQ,CAAC,YACtB,EAAW,QAAQ,CAAC,sBACpB,EAAW,QAAQ,CAAC,qBACpB,EAAW,QAAQ,CAAC,qBACpB,EAAW,QAAQ,CAAC,wBACpB,EAAW,QAAQ,CAAC,wBACpB,EAAW,QAAQ,CAAC,gBACpB,EAAW,QAAQ,CAAC,cACpB,EAAW,QAAQ,CAAC,SACpB,EAAW,QAAQ,CAAC,gBAIvC,IAAQ,EAAa,WAAY,GAEjC,IAAQ,EAAa,SAAU,GAI7B,EAAW,QAAQ,CAAC,sBAAwB,EAAW,QAAQ,CAAC,qBAAqB,AACvF,EAAgB,KAAK,GAAG,CAAC,EAAgB,EAAG,IAC5C,IAAa,EAAe,cACnB,EAAW,QAAQ,CAAC,qBAC7B,AADkD,EAClC,KAAK,GAAG,CAAC,EAAgB,EAAG,IAC5C,IAAa,EAAe,cACnB,EAAW,QAAQ,CAAC,wBAAwB,CACrD,EAAgB,KAAK,GAAG,CAAC,EAAgB,EAAG,IAC5C,IAAa,EAAe,aAEhC,GAGA,EAAW,EAAE,CAAC,QAAS,AAAC,IACtB,aAAa,GACb,IAAM,EAAU,KAAK,GAAG,GAClB,EAAW,EAAU,EAI3B,GAFA,IAAQ,EAAa,SAAU,CAAC,oBAAoB,EAAE,EAAK,KAAK,EAAE,KAAK,KAAK,CAAC,EAAW,KAAM;AAAG,CAAC,EAErF,IAAT,EAAY,CAEd,IAAQ,EAAa,SAAU,CAAC,iBAAiB,EAAE,WAAW;AAAE,CAAC,EACjE,IAAM,EAAiC,CACrC,GAAG,CAAe,CAClB,OAAQ,EAAA,aAAa,CAAC,OAAO,CAC7B,SAAU,IACV,CAFQ,OAEC,OACT,SACF,EACA,IAAa,IAAK,QAClB,EAAQ,EACV,KAAO,CAEL,IAAM,EAAc,AA0C5B,SAAS,AAAc,CAAmB,EACxC,IAAM,EAAc,EAAY,WAAW,UAE3C,AAAI,EAAY,QAAQ,CAAC,0BAA4B,EAAY,QAAQ,CAAC,iBACjE,CADmF,kBAIxF,EAAY,QAAQ,CAAC,yBAA2B,EAAY,QAAQ,CAAC,aAChE,CAD8E,YAInF,EAAY,QAAQ,CAAC,YAAc,EAAY,QAAQ,CAAC,cACnD,CADkE,gBAIvE,EAAY,QAAQ,CAAC,WAChB,CAD4B,UAIjC,EAAY,QAAQ,CAAC,qBAChB,CADsC,iBAI3C,EAAY,QAAQ,CAAC,kBAChB,CADmC,SAKrC,EAAY,KAAK,CAAC,EAAG,MAAQ,CAAD,CAAa,MAAM,CAAG,IAAM,MAAQ,EAAA,CACzE,AAD2E,EAtEjC,GAClC,IAAQ,EAAa,SAAU,CAAC,aAAa,EAAE,YAAY;AAAE,CAAC,EAC9D,IAAQ,EAAa,SAAU,CAAC;AAAU,EAAE,YAAY;AAAE,CAAC,EAE3D,IAAM,EAAiC,CACrC,GAAG,CAAe,CAClB,OAAQ,EAAA,aAAa,CAAC,MAAM,CAC5B,SAAU,EACV,IAFQ,IAEC,OACT,MAAO,GAAe,CAAC,aAAa,EAAE,EAAA,CAAM,SAC5C,CACF,EACA,IAAU,CAAA,EAAG,EAAY,EAAE,EAAE,EAAc,KAAK,CAAA,CAAE,EAClD,EAAQ,EACV,CACF,GAGA,EAAW,EAAE,CAAC,QAAS,AAAC,IACtB,aAAa,GACb,IAAQ,EAAa,SAAU,CAAC,mBAAmB,EAAE,EAAM,OAAO,CAAC;AAAE,CAAC,EACtE,IAAQ,EAAa,SAAU,CAAC,OAAO,EAAE,EAAM,KAAK,EAAI,iBAAiB;AAAE,CAAC,EAE5E,IAAM,EAA+B,CACnC,GAAG,CAAe,CAClB,OAAQ,EAAA,aAAa,CAAC,MAAM,CAC5B,SAAU,EACV,IAFQ,IAEC,SACT,MAAO,CAAC,QAAQ,EAAE,EAAM,OAAO,CAAA,CAAE,CACjC,QAAS,KAAK,GAAG,EACnB,EACA,IAAU,CAAA,EAAG,EAAY,EAAE,EAAE,EAAM,OAAO,CAAA,CAAE,EAC5C,EAAQ,EACV,EACF,EACF,CA2CO,SAAS,EAAc,CAAW,EAEvC,MADsB,AACf,mCAAc,IAAI,CAAC,EAC5B,CAOO,SAAS,EAAoB,CAAmB,EACrD,OAAO,EAAY,OAAO,CAAC,mBAAoB,GACjD,CAiBO,eAAe,EAAmB,CAAqB,CAAE,CAAmB,EACjF,GAAI,CACF,IAAM,EAAc,CAAA,EAAA,EAAA,IAAA,AAAG,EAAE,EAAe,GAGxC,GAAI,CAAC,CAAA,EAAA,EAAA,UAAA,AAAS,EAAE,GACd,CAJkB,KAIX,CACL,IAF0B,IAElB,EACR,IAHC,GAGO,aACR,cAAc,CAChB,EAIF,IAAM,EAAU,CAAA,EAAA,EAAA,IAAG,AAAH,EAAK,EAAa,QAClC,GAAI,CAAC,GAAA,EAAA,UAAA,AAAS,CADE,CACA,GACd,MAAO,CACL,AAFsB,QAEd,EACR,IAHC,GAGO,aACR,cAAc,CAChB,EAKF,GAAI,CADe,AACd,MADoB,EAAwB,GAG/C,CAFe,MACf,QAAQ,GAAG,CAAC,CAAC,cAAc,EAAE,EAAA,CAAa,EACnC,CACL,OAAQ,GACR,OAAQ,aACR,cAAc,CAChB,EAGF,MAAO,CACL,QAAQ,EACR,OAAQ,WACR,cAAc,CAChB,CACF,CAAE,MAAO,EAAO,CAEd,OADA,QAAQ,KAAK,CAAC,CAAC,KAAK,EAAE,EAAY,OAAO,CAAC,CAAE,GACrC,CACL,QAAQ,EACR,OAAQ,aACR,cAAc,CAChB,CACF,CACF,CAQO,eAAe,EAAmB,CAAqB,CAAE,CAAmB,EAEjF,MAAyB,aAAlB,CADQ,MAAM,EAAmB,EAAe,EAAA,EACzC,MAChB,AADsB,CAQtB,eAAe,EAAwB,CAAmB,EACxD,GAAI,CACF,IAAM,EAAU,CAAA,EAAA,EAAA,IAAA,AAAG,EAAE,EAAa,QAIlC,IAAK,IAAM,IADW,CAAC,GACJ,IADY,AAHf,SAGyB,OAAO,CACd,CAChC,IAAM,EAAW,CAAA,EAAA,EAAA,IAAA,AAAG,EAAE,EAAS,GAC/B,GAAI,CAAC,CAAA,EAAA,EAAA,UAAA,AAAS,EAAE,GACd,CAFe,KAER,EAEX,AAH6B,CAO7B,IAAM,EAAc,CADJ,KANT,CAMe,EAAA,QAAE,CAAC,OAAO,CAAC,EAAA,EACL,MAAM,CAAC,AAAC,GAA4B,KAD1C,IACgC,GAGtD,GAA2B,GAAG,CAA1B,EAAY,MAAM,CACpB,OAAO,EAIT,IAAM,EAAW,CAAA,EAAA,EAAA,IAAG,AAAH,EAAK,EAAS,QACzB,EAAc,MAAM,EAAA,QAAE,CAAC,CADZ,OACoB,CAAC,EAAU,SAChD,GAAI,CAAC,EAAY,CADS,GACL,IAAM,EAAY,QAAQ,CAAC,UAC9C,CADyD,MAClD,EAGT,OAAO,CACT,CAAE,MAAO,EAAO,CAEd,OADA,QAAQ,KAAK,CAAC,iBAAkB,IACzB,CACT,CACF,CAMO,eAAe,EAAyB,CAAmB,EAChE,GAAI,CACF,QAAQ,GAAG,CAAC,CAAC,YAAY,EAAE,EAAA,CAAa,EACxC,MAAM,EAAA,QAAE,CAAC,EAAE,CAAC,EAAa,CAAE,WAAW,EAAM,OAAO,CAAK,AAAlD,GACN,QAAQ,GAAG,CAAC,CAAC,MAAM,EAAE,EAAA,CAAa,CACpC,CAAE,MAAO,EAAO,CACd,QAAQ,KAAK,CAAC,CAAC,OAAO,EAAE,EAAY,CAAC,CAAC,CAAE,EAE1C,CACF,CAQO,eAAe,EACpB,CAAqB,CACrB,CAAsB,EAEtB,IAAM,EAAmC,CAAC,EAGpC,EAAS,EAAa,GAAG,CAAC,MAAO,IACrC,IAAM,EAAS,MAAM,EAAmB,EAAe,GACvD,CAAO,CAAC,EAAY,CAAG,CACzB,GAGA,OADA,MAAM,QAAQ,GAAG,CAAC,GACX,CACT,CAOO,eAAe,EAAoB,CAAmB,EAC3D,OAAO,IAAI,QAAQ,AAAC,IAElB,GAAI,CAAC,CAAA,EAAA,EAAA,UAAA,AAAS,EAAE,GAAc,YAC5B,EAAQ,CACN,MAFC,GAEQ,EACT,MAAO,CAAC,SAAS,EAAE,EAAA,CAAa,AAClC,GAKF,IAAM,EAAgB,CAAA,EAAA,EAAA,KAAA,AAAI,EAAE,SAAU,CAAC,EAAY,CAAE,CACnD,MAAO,CAAC,QADY,CACF,OAAQ,OAAO,CACjC,UAAU,EACV,IAAK,CACH,GAAG,QAAQ,GAAG,CACd,SAAU,aACZ,CACF,GAEI,EAAc,GAGZ,EAAY,WAAW,KAC3B,EAAc,IAAI,CAAC,WACnB,EAAQ,CACN,SAAS,EACT,MAAO,eACT,EACF,EAAG,KAGH,EAAc,MAAM,EAAE,GAAG,OAAQ,AAAC,IAChC,GAAe,EAAK,QAAQ,EAC9B,GAGA,EAAc,EAAE,CAAC,OAAQ,AAAC,IACxB,aAAa,GAEA,GAAG,CAAZ,EACF,EAAQ,CAAE,SAAS,CAAK,GAExB,EAAQ,CACN,SAAS,EACT,MAAO,CAAC,aAAa,EAAE,EAAA,EAAO,EAAc,CAAC,MAAM,EAAE,EAAA,CAAa,CAAG,GAAA,CAAI,AAC3E,EAEJ,GAGA,EAAc,EAAE,CAAC,QAAS,AAAC,IACzB,aAAa,GAET,EAAM,OAAO,CAAC,QAAQ,CAAC,UACzB,CADoC,CAC5B,CACN,SAAS,EACT,MAAO,4CACT,GAEA,EAAQ,CACN,SAAS,EACT,MAAO,CAAC,cAAc,EAAE,EAAM,OAAO,CAAA,CACvC,AADyC,EAG7C,GAGA,EAAc,KAAK,EACrB,EACF,kJCleA,IAAA,EAAA,EAAA,CAAA,CAAA,OACA,EAAA,EAAA,CAAA,CAAA,OAUO,eAAe,EACpB,CAAmB,CACnB,CAA4B,CAC5B,CAAqB,EAOrB,IAAM,EAAc,CAAA,EAAA,EAAA,IAAA,AAAG,EAAE,EAAe,GAClC,EAAyB,EAAE,CAC3B,EAAyB,EAAE,CAEjC,GAAI,CACF,IAAM,EAAO,EAAc,GALT,CAKa,EAAI,CAAC,EACpC,IAAK,IAAM,KAAW,EAAM,CAC1B,IAAM,EAAY,CAAI,CAAC,EAAQ,CAC/B,GAAI,EAAU,WAAW,EAAI,EAAU,QAAQ,CAAE,CAC/C,IAAM,EAAW,CAAA,EAAA,EAAA,IAAA,AAAG,EAAE,EAAa,EAAU,WAAW,EAExD,GAAI,CACF,MAAM,EAAA,CAHS,OAGP,CAAC,MAAM,CAAC,GAEhB,EAAa,IAAI,CAAC,EAAU,QAFtB,GAEiC,CACzC,CAAE,KAAM,CAEN,IAAM,EAAkB,EAAU,QAAQ,CAAC,EAAU,YAAY,CAAC,EAAI,GAChE,EAAU,CAAA,EAAG,EAAU,QAAQ,CAAC,CAAC,EAAE,EAAA,CAAiB,AAC1D,OAAM,EAAA,QAAE,CAAC,SAAS,CAAC,EAAU,EAAS,SACtC,EAAa,EADP,EACW,CAAC,EAAU,WAAW,CACzC,CACF,CACF,CACA,MAAO,CAAE,SAAS,eAAM,eAAc,CAAa,CACrD,CAAE,MAAO,EAAO,CACd,IAAM,EAAe,aAAiB,MAAQ,EAAM,OAAO,CAAG,OAAO,GAErE,OADA,QAAQ,KAAK,CAAC,CAAC,KAAK,EAAE,EAAY,WAAW,CAAC,CAAE,GACzC,CAAE,SAAS,eAAO,eAAc,EAAc,MAAO,CAAa,CAC3E,CACF,CAQO,eAAe,EACpB,CAAmB,CACnB,CAAqB,EAOrB,IAAM,EAAc,CAAA,EAAA,EAAA,IAAA,AAAG,EAAE,EAAe,GAClC,EAAW,CAAA,EAAA,EAAA,IAAA,AAAG,EAAE,EAAa,SAC7B,CAFc,CAEiB,EAAE,CACjC,EAA+B,EAAE,CAEvC,GAAI,CAEF,GAAI,CACF,CAPa,KAOP,EAAA,QAAE,CAAC,MAAM,CAAC,GAChB,EAAmB,IAAI,CAAC,QAC1B,CAAE,CAFM,IAEA,CACN,MAAM,EAAA,QAAE,CAAC,KAAK,CAAC,EAAU,CAAE,WAAW,CAAK,GAC3C,EAAmB,CADb,GACiB,CAAC,QAC1B,CAEA,MAAO,CAAE,QAAS,sBAAM,qBAAoB,CAAmB,CACjE,CAAE,MAAO,EAAO,CACd,IAAM,EAAe,aAAiB,MAAQ,EAAM,OAAO,CAAG,OAAO,GAErE,OADA,QAAQ,KAAK,CAAC,CAAC,KAAK,EAAE,EAAY,aAAa,CAAC,CAAE,GAC3C,CAAE,SAAS,qBAAO,qBAAoB,EAAoB,MAAO,CAAa,CACvF,CACF,CAUO,eAAe,EACpB,CAAmB,CACnB,CAAe,CACf,CAA4B,CAC5B,CAAqB,EAMrB,GAAI,CACF,IAAM,EAAY,EAAc,IAAI,CAAC,EAAQ,CAE7C,GAAI,CAAC,EACH,MAAO,CACL,EAFY,OAEH,EACT,MAAO,CAAC,GAAG,EAAE,EAAQ,QAAQ,EAAE,EAAY,IAAI,CAAC,AAClD,EAGF,GAAI,CAAC,EAAU,WAAW,EAAI,CAAC,EAAU,QAAQ,CAC/C,CADiD,KAC1C,CACL,SAAS,EACT,MAAO,CAAC,GAAG,EAAE,EAAQ,6BAA6B,CAAC,AACrD,EAGF,IAAM,EAAc,CAAA,EAAA,EAAA,IAAG,AAAH,EAAK,EAAe,GAClC,EAAW,CAAA,EAAA,EAAA,IAAA,AAAG,EAAE,EAAa,EAAU,QADzB,GACoC,EAGlD,EAAkB,EAAU,QAAQ,CAAC,AAH1B,EAGoC,YAAY,CAAC,EAAI,EAAU,YAAY,CACtF,EAAU,CAAA,EAAG,EAAU,QAAQ,CAAC,CAAC,EAAE,EAAA,CAAiB,CAO1D,OAJA,MAAM,EAAA,QAAE,CAAC,SAAS,CAAC,EAAU,EAAS,SAEtC,IAFM,IAEE,GAAG,CAAC,CAAC,SAAS,EAAE,EAAS,MAAM,EAAE,EAAA,CAAS,EAE3C,CACL,SAAS,EACT,YAAa,EAAU,WAAW,AACpC,CACF,CAAE,MAAO,EAAO,CACd,IAAM,EAAe,aAAiB,MAAQ,EAAM,OAAO,CAAG,OAAO,GAErE,OADA,QAAQ,KAAK,CAAC,CAAC,KAAK,EAAE,EAAY,IAAI,EAAE,EAAQ,UAAU,CAAC,CAAE,GACtD,CACL,QAAS,GACT,MAAO,CACT,CACF,CACF,mGCnJC,EAAA,CAAA,CAAA,6BACM,OAAM,EACH,QAAU,IAAI,GAAwB,CACtC,MAAuC,EAAE,AAAC,CACjC,aAAsB,AAEvC,aAAY,CAAqB,CAAE,CACjC,IAAI,CAAC,aAAa,CAAG,CACvB,CAOA,MAAM,IAAO,CAAsB,CAAc,CAC/C,OAAO,IAAI,QAAW,CAAC,EAAS,KAC9B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UACd,GAAI,CACF,IAAM,EAAS,MAAM,IAErB,OADA,EAAQ,GACD,CACT,CAAE,MAAO,EAAO,CAEd,MADA,EAAO,GACD,CACR,CACF,GAEA,IAAI,CAAC,OAAO,EACd,EACF,CAKA,MAAc,SAAyB,CACrC,GAAI,IAAI,CAAC,OAAO,CAAC,IAAI,EAAI,IAAI,CAAC,aAAa,EAA0B,GAAG,CAAzB,IAAI,CAAC,KAAK,CAAC,MAAM,CAC9D,OAGF,IAAM,EAAO,IAAI,CAAC,KAAK,CAAC,KAAK,GAC7B,GAAI,CAAC,EAAM,OAEX,IAAM,EAAU,IAAO,OAAO,CAAC,KAC7B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GACpB,IAAI,CAAC,OAAO,EACd,EADkB,CAGlB,IAAI,CAAC,MAHyB,CAGlB,CAAC,GAAG,CAAC,EACnB,CAKA,MAAM,YAA4B,CAChC,KAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAG,GAAK,IAAI,CAAC,KAAK,CAAC,MAAM,CAAG,EAAG,CACjD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAG,GAAG,AACzB,MAAM,QAAQ,IAAI,CAAC,IAAI,CAAC,OAAO,EAIjC,IAAI,CAAC,OAAO,EAEhB,CAKA,WAAY,CACV,MAAO,CACL,QAAS,IAAI,CAAC,OAAO,CAAC,IAAI,CAC1B,OAAQ,IAAI,CAAC,KAAK,CAAC,MAAM,CACzB,cAAe,IAAI,CAAC,aAAa,AACnC,CACF,CACF,mEC9EA,IAAA,EAAA,EAAA,CAAA,CAAA,OAOA,EAAA,EAAA,CAAA,CAAA,OACA,EAAA,EAAA,CAAA,CAAA,OAKA,EAAA,EAAA,CAAA,CAAA,OACA,EAAA,EAAA,CAAA,CAAA,OAMO,eAAe,IACpB,IAAM,EAAU,IAAI,YAGd,EAAS,IAAI,eAAe,CAChC,MAAM,MAAM,CAAU,EACpB,GAAI,CAEF,IAAM,EAAU,AAAC,IAEG,gBAAd,EAAK,IAAI,EAA8C,UAAU,AAAlC,OAAO,EAAK,OAAO,EAEhD,EAAK,OAAO,CAAC,MAAM,GAAG,KACxB,EAAK,EAD4B,KACrB,CAAG,EAAK,OAAO,CAAC,KAAK,CAAC,EAFpB,CAEuB,GAFnB,EAE8B,IAFxB,MAAM,SAEkB,EAIpD,IAAM,EAAU,CAAC,MAAM,EAAE,KAAK,SAAS,CAAC,MAAM;AAAA;AAAI,CAAC,CACnD,EAAW,OAAO,CAAC,EAAQ,MAAM,CAAC,GACpC,EAGM,EAAqB,MACzB,EACA,EACA,EAAe,EAAE,IAGjB,EAAQ,CACN,KAAM,mCACN,EACA,QAAS,CAAC,IAAI,EAAE,EAAY,aAAa,CAAC,CAC1C,SAAU,CACZ,GAEA,IAAM,EAAY,MAAM,GAAA,EAAA,qBAAA,AAAoB,EAAE,EAAa,EAAQ,GAEnE,IAAI,EAAU,AAFU,OAEH,CAcd,YACL,EAAQ,CACN,KAAM,iCACN,EACA,QAAS,CAAC,IAAI,EAAE,EAAY,WAAW,EAAE,EAAU,KAAK,CAAA,CAAE,CAC1D,MAAO,EAAU,KAAK,CACtB,SAAU,EAAe,CAC3B,EArBqB,EACrB,IAAI,EAAU,CAAC,GAAG,EAAE,EAAY,UAAU,CAAC,CACvC,EAAU,YAAY,CAAC,MAAM,CAAG,GAAG,CACrC,GAAW,CAAC,KAAK,EAAE,EAAU,YAAY,CAAC,IAAI,CAAC,MAAM,EAAE,AAAD,EAEpD,EAAU,YAAY,CAAC,MAAM,CAAG,GAAG,CACrC,GAAW,CAAC,SAAS,EAAE,EAAU,YAAY,CAAC,IAAI,CAAC,MAAM,EAAC,AAAC,EAE7D,EAAQ,CACN,KAAM,sBACN,sBACA,EACA,SAAU,EAAe,CAC3B,EACF,CAYA,EAAQ,CACN,KAAM,oCACN,EACA,QAAS,CAAC,IAAI,EAAE,EAAY,cAAc,CAAC,CAC3C,SAAU,EAAe,CAC3B,GAEA,IAAM,EAAa,MAAM,CAAA,EAAA,EAAA,4BAAA,AAA2B,EAAE,EAAa,GAEnE,CAFyB,EAErB,EAAW,OAAO,CAAE,CACtB,IAAI,EAAU,CAAC,GAAG,EAAE,EAAY,cAAc,CAAC,CAC3C,EAAW,kBAAkB,CAAC,MAAM,CAAG,GAAG,CAC5C,GAAW,CAAC,KAAK,EAAE,EAAW,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,EAE5D,EAAW,kBAAkB,CAAC,MAAM,CAAG,GAAG,CAC5C,GAAW,CAAC,SAAS,EAAE,EAAW,kBAAkB,CAAC,IAAI,CAAC,MAAM,EAAC,AAAC,EAEpE,EAAQ,CACN,KAAM,mCACN,UACA,EACA,SAAU,EAAe,CAC3B,EACF,MACE,CADK,CACG,CACN,KAAM,kCACN,EACA,QAAS,CAAC,IAAI,EAAE,EAAY,aAAa,EAAE,EAAW,KAAK,CAAA,CAAE,CAC7D,MAAO,EAAW,KAAK,CACvB,SAAU,EAAe,CAC3B,EAEJ,EAGA,EAAQ,CACN,KAAM,iBACN,QAAS,eACT,SAAU,CACZ,GAGA,IAAM,EAAgB,EAAA,gBAAgB,CAAC,cAAc,CAC/C,EAAe,EADC,IACK,CAAA,EAAA,EAAA,wBAAA,AAAuB,EAAE,GAEpD,GAAI,CAAC,EAAa,CAFS,MAEF,CAAE,CACzB,EAAQ,CACN,KAAM,QACN,QAAS,EAAa,KAAK,CAC3B,SAAU,CACZ,GACA,EAAW,KAAK,GAChB,MACF,CAEA,EAAQ,CACN,KAAM,oBACN,QAAS,CAAC,SAAS,EAAE,EAAA,CAAe,CACpC,SAAU,EACZ,GAGA,IAAM,EAAiB,MAAM,GAAA,EAAA,iBAAA,AAAgB,IACvC,EAAiB,OAAO,MADD,CACQ,CAAC,GAChC,EAAgB,EAAe,MAAM,CAE3C,GAAsB,IAAlB,EAAqB,CACvB,EAAQ,CACN,KAAM,QACN,QAAS,cACT,SAAU,EACZ,GACA,EAAW,KAAK,GAChB,MACF,CAEA,EAAQ,CACN,KAAM,kBACN,QAAS,CAAC,GAAG,EAAE,EAAc,QAAQ,CAAC,CACtC,SAAU,EAAe,GAAG,CAAC,CAAC,CAAC,EAAK,GAAK,GACzC,SAAU,EACZ,GAGA,IAAM,EAA+B,CACnC,SAAS,gBACT,EACA,aAAc,EACd,YAAa,EACb,eAAgB,EAAE,eAClB,EACA,SAAU,CACZ,EAEM,EAAY,KAAK,GAAG,GAGpB,EAAe,MAAM,CAAA,EAAA,EAAA,0BAAA,AAAyB,EAAE,EAAe,EAAe,GAAG,CAAC,AAA7D,CAA8D,CAAC,EAAK,GAAK,IAC9F,EAAmB,EAAe,MAAM,CAAC,CAAC,CAAC,EAAY,GAAK,CAAY,CAAC,EAAY,EACrF,EAAkB,EAAe,MAAM,CAAC,CAAC,CAAC,EAAY,GAAK,CAAC,CAAY,CAAC,EAAY,EAG3F,IAAK,GAAM,CAAC,EAAa,EAAO,GAAI,EAClC,EAAQ,CACN,KAAM,OAF4C,wBAGlD,EACA,QAAS,CAAC,GAAG,EAAE,EAAY,SAAS,CACtC,AADuC,GAEvC,MAAM,EAAmB,EAAa,EAAyB,IAMjE,GAFA,EAAO,YAAY,CAAG,EAAiB,MAAM,CAEd,IAA3B,EAAgB,MAAM,CAAQ,CAChC,EAAQ,CACN,KAAM,aACN,QAAS,CAAC,GAAG,EAAE,EAAc,aAAa,CAAC,CAC3C,SAAU,IACV,OAAQ,CACN,SAAS,gBACT,EACA,aAAc,EACd,YAAa,EACb,eAAgB,EAAE,eAClB,EACA,SAAU,KAAK,GAAG,GAAK,CACzB,CACF,GACA,EAAW,KAAK,GAChB,MACF,CAEA,IAAM,EAAmB,EAAA,gBAAgB,CAAC,mBAAjB,EAAsC,CAE/D,EAAQ,CACN,KAAM,oBACN,QAAS,CAAC,GAAG,EAAE,EAAiB,MAAM,CAAC,QAAQ,EAAE,EAAgB,MAAM,CAAC,cAAc,EAAE,EAAiB,CAAC,CAAC,eAC3G,EACA,gBAAiB,EAAgB,MAAM,CACvC,iBAAkB,EAAiB,MAAM,CACzC,SAAU,EACZ,GAGA,IAAM,EAAuB,IAAI,EAAA,oBAAoB,CAAC,GAGhD,EAAe,IAAI,IAOnB,EAV2B,AAUd,EAAgB,GAAG,CAAC,CAAC,CAAC,EAAa,EAAO,CAAE,IACtD,EAAqB,GAAG,CAAC,UAC9B,IAAM,EAAe,GAAc,GAAR,EAAc,CAAC,EAAgB,MAAM,GAAI,CAAC,CAErE,EAAQ,CACN,KAAM,4BACN,EACA,QAAS,CAAC,QAAQ,EAAE,EAAY,EAAE,EAAE,EAAQ,EAAE,CAAC,EAAE,EAAgB,MAAM,CAAC,CAAC,CAAC,CAC1E,SAAU,KAAK,KAAK,CAAC,EACvB,GAEA,GAAI,CACF,IAAM,EAAc,MAAM,CAAA,EAAA,EAAA,eAAA,AAAc,EAAE,CACxC,QAAS,EAAO,IAAI,CACpB,GAFwB,OAEb,EACX,QAAS,EAAA,gBAAgB,CAAC,WAAW,CACrC,OADS,IACG,CAAC,EAAkB,KAC7B,IAAM,EAAmB,KAAK,KAAK,CAAC,EAA2B,GAAX,EAAiB,CAAC,AAAgC,KAA/B,EAAgB,MAAM,GAAI,CAAC,AAAI,CAAG,EACzG,EAAQ,CACN,KAAM,+BACN,EACA,SAAU,KAAK,GAAG,CAAC,EAAkB,YACrC,CACF,EACF,EACA,QAAS,AAAC,IACR,EAAQ,CACN,KAAM,4BACN,QACA,EACA,SAAU,KAAK,KAAK,CAAC,EAAe,IAAM,CAAD,CAAiB,MAAM,GAAI,CAAC,CACvE,EACF,EACA,MAAO,CAAC,EAAwB,EAA2C,KACzE,EAAQ,CACN,KAAM,cACN,YAAa,UACb,UACA,EACA,UAAW,KAAK,GAAG,EACrB,EACF,CACF,GAEI,EAAY,MAAM,GAAK,EAAA,aAAa,CAAC,OAAO,EAAE,AAChD,EAAa,GAAG,CAAC,EAAa,CAAE,IADP,GACe,EAAA,aAAa,CAAC,OAAO,CAAE,OAAQ,CAAY,GAEnF,EAAQ,CAFgC,AAGtC,KAAM,8BACN,EACA,QAAS,CAAC,GAAG,EAAE,EAAY,KAAK,CAAC,CACjC,SAAU,KAAK,KAAK,CAAC,EAAe,IAAM,CAAD,CAAiB,MAAM,GAAI,CAAC,EACrE,OAAQ,CACV,GAGA,MAAM,EACJ,EACA,EACA,KAAK,KAAK,CAAC,EAAe,IAAM,CAAD,CAAiB,MAAM,GAAI,CAAC,KAI7D,EAAa,GAAG,CAAC,EAAa,CAC5B,OAAQ,EAAA,aAAa,CAAC,MAAM,CAC5B,MAAO,EAAY,KAAK,CACxB,CAFQ,MAEA,CACV,GAEA,EAAQ,CACN,KAAM,6BACN,EACA,QAAS,CAAC,GAAG,EAAE,EAAY,OAAO,EAAE,EAAY,KAAK,CAAA,CAAE,CACvD,SAAU,KAAK,KAAK,CAAC,EAAe,IAAM,CAAD,CAAiB,MAAM,GAAI,CAAC,EACrE,OAAQ,CACV,GAEJ,CAAE,MAAO,EAAO,CACd,IAAM,EAAe,aAAiB,MAAQ,EAAM,OAAO,CAAG,OAAO,GACrE,EAAa,GAAG,CAAC,EAAa,CAC5B,OAAQ,EAAA,aAAa,CAAC,MAAM,CAC5B,MAAO,CACT,GAEA,EAAQ,CACN,EALQ,GAKF,6BACN,EACA,QAAS,CAAC,GAAG,EAAE,EAAY,OAAO,EAAE,EAAA,CAAc,CAClD,MAAO,EACP,SAAU,KAAK,KAAK,CAAC,EAAe,IAAM,CAAD,CAAiB,MAAM,GAAI,CAAC,CACvE,EACF,CACF,IAOF,IAAK,GAAM,CAAC,EAAa,EAAY,GAHrC,MAAM,QAAQ,GAAG,CAAC,GAGuB,GACnC,EAAY,MAAM,EAD+B,CAC1B,EAAA,aAAa,CAAC,OAAO,CAC9C,CADgD,CACzC,YADkB,AACN,IAEnB,EAAO,WAAW,GAClB,EAAO,cAAc,CAAC,IAAI,CAAC,IAK/B,EAAO,QAAQ,CAAG,KAAK,GAAG,GAAK,EAC/B,EAAO,OAAO,CAA0B,IAAvB,EAAO,WAAW,CAEnC,EAAQ,CACN,KAAM,aACN,QAAS,EAAO,OAAO,CACnB,CAAC,YAAY,EAAE,EAAO,YAAY,CAAC,MAAM,EAAE,KAAK,KAAK,CAAC,EAAO,QAAQ,CAAG,KAAM,CAAC,CAAC,CAChF,CAAC,aAAa,EAAE,EAAO,YAAY,CAAC,MAAM,EAAE,EAAO,WAAW,CAAC,MAAM,EAAE,KAAK,KAAK,CAAC,EAAO,QAAQ,CAAG,KAAM,CAAC,CAAC,CAChH,SAAU,WACV,CACF,GAEA,EAAW,KAAK,EAClB,CAAE,MAAO,EAAO,CACd,IAAM,EAAe,aAAiB,MAAQ,EAAM,OAAO,CAAG,OAAO,GACrE,QAAQ,KAAK,CAAC,aAAc,GAE5B,IAAM,EAAY,CAAC,MAAM,EAAE,KAAK,SAAS,CAAC,CACxC,KAAM,QACN,QAAS,CAAC,WAAW,EAAE,EAAA,CAAc,CACrC,MAAO,EACP,SAAU,CACZ,GAAG;AAAA;AAAI,CAAC,CAER,EAAW,OAAO,CAAC,EAAQ,MAAM,CAAC,IAClC,EAAW,KAAK,EAClB,CACF,CACF,GAEA,OAAO,IAAI,SAAS,EAAQ,CAC1B,QAAS,CACP,eAAgB,oBAChB,gBAAiB,WACjB,WAAc,aACd,8BAA+B,IAC/B,+BAAgC,eAClC,CACF,EACF,gKClYA,IAAA,EAGO,EAAA,CAFLA,AAEK,CAAA,OACP,EAA0B,EAAyB,CAA1CC,AAA0C,CAAA,GAAA,EAH9B,EAIrB,CADkB,CAD2C,AAEnB,EAAA,CAAjCC,AAAiC,CAFnC,AAEmC,GADhB,CAC8C,GAExE,EAAwC,EAAA,CAAA,CAFjBC,AAEiB,EAA5BC,KAWZ,IAbkC,AAa5BC,EAAc,GAXM,CAWN,EAbsB,AAalBL,YAXgB,OAWhBA,CAAoB,CAC1CM,WAAY,CACVC,KAAMN,EAAAA,SAAAA,CAAUO,SAAS,CACzBC,KAAM,kCACNC,SAAU,4BACVC,SAAU,QACVC,WAAY,EACd,EACAC,iBAAkB,sEAClBC,iBAXF,CAA0B,WAYxBV,CACF,GAKM,CAAEW,kBAAgB,sBAAEC,CAAoB,aAAEC,CAAW,CAAE,CAAGZ,EAEhE,SAASH,IACP,MAAA,CAAA,EAAA,EAAOC,UAAAA,EAAY,kBACjBY,uBACAC,CACF,EACF","ignoreList":[6]}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
module.exports={83886:function(e){var{g:r,__dirname:t,m:s,e:n}=e;s.exports=e.x("fs",()=>require("fs"))},45935:function(e){var{g:r,__dirname:t,m:s,e:n}=e;s.exports=e.x("next/dist/server/app-render/after-task-async-storage.external.js",()=>require("next/dist/server/app-render/after-task-async-storage.external.js"))},35692:e=>{"use strict";var{g:r,__dirname:t}=e;e.s({ProjectStatus:()=>i,getProjectsConfig:()=>o,saveProjectsConfig:()=>c});var s=e.i(9892),n=e.i(88941);async function o(){try{await (0,s.access)(n.PROJECT_CONFIG_PATH,s.constants.F_OK)}catch{return await c({}),{}}try{let e=await (0,s.readFile)(n.PROJECT_CONFIG_PATH,"utf-8");if(!e)return{};return JSON.parse(e)}catch(e){throw console.error("读取或解析项目配置文件失败:",e),Error("无法加载项目配置")}}async function c(e){let r=n.PROJECT_CONFIG_PATH+".tmp";try{await (0,s.writeFile)(r,JSON.stringify(e,null,2),"utf-8"),await (0,s.rename)(r,n.PROJECT_CONFIG_PATH)}catch(e){throw console.error("保存项目配置文件失败:",e),Error("无法保存项目配置")}}var i=function(e){return e.PENDING="pending",e.EXISTING="existing",e.CLONING="cloning",e.SUCCESS="success",e.FAILED="failed",e.RETRYING="retrying",e}({})},
|
|
1
|
+
module.exports={83886:function(e){var{g:r,__dirname:t,m:s,e:n}=e;s.exports=e.x("fs",()=>require("fs"))},45935:function(e){var{g:r,__dirname:t,m:s,e:n}=e;s.exports=e.x("next/dist/server/app-render/after-task-async-storage.external.js",()=>require("next/dist/server/app-render/after-task-async-storage.external.js"))},35692:e=>{"use strict";var{g:r,__dirname:t}=e;e.s({ProjectStatus:()=>i,getProjectsConfig:()=>o,saveProjectsConfig:()=>c});var s=e.i(9892),n=e.i(88941);async function o(){try{await (0,s.access)(n.PROJECT_CONFIG_PATH,s.constants.F_OK)}catch{return await c({}),{}}try{let e=await (0,s.readFile)(n.PROJECT_CONFIG_PATH,"utf-8");if(!e)return{};return JSON.parse(e)}catch(e){throw console.error("读取或解析项目配置文件失败:",e),Error("无法加载项目配置")}}async function c(e){let r=n.PROJECT_CONFIG_PATH+".tmp";try{await (0,s.writeFile)(r,JSON.stringify(e,null,2),"utf-8"),await (0,s.rename)(r,n.PROJECT_CONFIG_PATH)}catch(e){throw console.error("保存项目配置文件失败:",e),Error("无法保存项目配置")}}var i=function(e){return e.PENDING="pending",e.EXISTING="existing",e.CLONING="cloning",e.SUCCESS="success",e.FAILED="failed",e.RETRYING="retrying",e}({})},29549:function(e){var{g:r,__dirname:t,m:s,e:n}=e;s.exports=e.x("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js",()=>require("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js"))},83943:function(e){var{g:r,__dirname:t,m:s,e:n}=e;s.exports=e.x("next/dist/server/app-render/work-unit-async-storage.external.js",()=>require("next/dist/server/app-render/work-unit-async-storage.external.js"))},86103:function(e){var{g:r,__dirname:t,m:s,e:n}=e;s.exports=e.x("next/dist/server/app-render/work-async-storage.external.js",()=>require("next/dist/server/app-render/work-async-storage.external.js"))},30331:function(e){var{g:r,__dirname:t,m:s,e:n}=e;s.exports=e.x("path",()=>require("path"))},23430:function(e){var{g:r,__dirname:t,m:s,e:n}=e;s.exports=e.x("next/dist/compiled/@opentelemetry/api",()=>require("next/dist/compiled/@opentelemetry/api"))},13442:function(e){var{g:r,__dirname:t,m:s,e:n}=e;s.exports=e.x("os",()=>require("os"))},52670:function(e){var{g:r,__dirname:t,m:s,e:n}=e;s.exports=e.x("next/dist/compiled/next-server/app-route-turbo.runtime.prod.js",()=>require("next/dist/compiled/next-server/app-route-turbo.runtime.prod.js"))},88941:e=>{"use strict";var{g:r,__dirname:t}=e;{e.s({PROJECT_CONFIG_PATH:()=>t,ProjectStatus:()=>o,WORKSPACE_CONFIG:()=>r});var s=e.i(13442),n=e.i(30331);let r={WORKSPACE_ROOT:(0,n.join)((0,s.homedir)(),"Documents","prime-workspace"),GIT_TIMEOUT:3e5,MAX_CONCURRENT_CLONES:Math.max(2,Math.min((0,s.cpus)().length,8)),MAX_RETRY_ATTEMPTS:3},t=(0,n.join)((0,s.homedir)(),".prime-projects.json");var o=function(e){return e.PENDING="pending",e.EXISTING="existing",e.CLONING="cloning",e.SUCCESS="success",e.FAILED="failed",e.RETRYING="retrying",e.INCOMPLETE="incomplete",e}({})}},9892:function(e){var{g:r,__dirname:t,m:s,e:n}=e;s.exports=e.x("fs/promises",()=>require("fs/promises"))},15079:e=>{"use strict";var{g:r,__dirname:t}=e;e.s({createProjectEnvFiles:()=>o,createProjectMockDirectories:()=>c,updateProjectEnvFile:()=>i});var s=e.i(83886),n=e.i(30331);async function o(e,r,t){let o=(0,n.join)(t,e),c=[],i=[];try{let e=r.envs||{};for(let r in e){let t=e[r];if(t.envFileName&&t.proxyKey){let e=(0,n.join)(o,t.envFileName);try{await s.promises.access(e),i.push(t.envFileName)}catch{let r=t.proxyEnv[t.currentProxy]||"",n=`${t.proxyKey}=${r}`;await s.promises.writeFile(e,n,"utf-8"),c.push(t.envFileName)}}}return{success:!0,createdFiles:c,skippedFiles:i}}catch(t){let r=t instanceof Error?t.message:String(t);return console.error(`在为项目 ${e} 创建环境文件时出错:`,t),{success:!1,createdFiles:c,skippedFiles:i,error:r}}}async function c(e,r){let t=(0,n.join)(r,e),o=(0,n.join)(t,".mock"),c=[],i=[];try{try{await s.promises.access(o),i.push(".mock")}catch{await s.promises.mkdir(o,{recursive:!0}),c.push(".mock")}return{success:!0,createdDirectories:c,skippedDirectories:i}}catch(t){let r=t instanceof Error?t.message:String(t);return console.error(`在为项目 ${e} 创建Mock目录时出错:`,t),{success:!1,createdDirectories:c,skippedDirectories:i,error:r}}}async function i(e,r,t,o){try{let c=t.envs[r];if(!c)return{success:!1,error:`环境 ${r} 不存在于项目 ${e} 配置中`};if(!c.envFileName||!c.proxyKey)return{success:!1,error:`环境 ${r} 缺少 envFileName 或 proxyKey 配置`};let i=(0,n.join)(o,e),a=(0,n.join)(i,c.envFileName),u=c.proxyEnv[c.currentProxy]||c.currentProxy,p=`${c.proxyKey}=${u}`;return await s.promises.writeFile(a,p,"utf-8"),console.log(`已更新环境文件: ${a}, 内容: ${p}`),{success:!0,updatedFile:c.envFileName}}catch(s){let t=s instanceof Error?s.message:String(s);return console.error(`更新项目 ${e} 环境 ${r} 的环境文件时出错:`,s),{success:!1,error:t}}}},24468:function(e){var{g:r,__dirname:t,m:s,e:n}=e},32875:e=>{"use strict";var{g:r,__dirname:t}=e;e.s({GET:()=>i,PUT:()=>a});var s=e.i(15494),n=e.i(35692),o=e.i(15079),c=e.i(88941);async function i(e){try{let{searchParams:r}=new URL(e.url),t=r.get("project");if(!t)return s.NextResponse.json({success:!1,error:"项目名称参数缺失"},{status:400});let o=await (0,n.getProjectsConfig)();if(!o[t])return s.NextResponse.json({success:!1,error:`项目 ${t} 不存在`},{status:404});let c=o[t];return s.NextResponse.json({success:!0,data:{projectName:t,repo:c.repo,mockingIntercept:c.mockingIntercept,mockOpen:c.mockOpen,envs:c.envs}})}catch(r){let e=r instanceof Error?r.message:"获取项目配置失败";return console.error("获取项目配置失败:",r),s.NextResponse.json({success:!1,error:e},{status:500})}}async function a(e){try{let{projectName:r,envName:t,newProxy:i,customProxyUrl:a,projectConfig:u}=await e.json();if(!r)return s.NextResponse.json({success:!1,error:"缺少必要参数:projectName"},{status:400});if(u){let e=await (0,n.getProjectsConfig)();if(!e[r])return s.NextResponse.json({success:!1,error:`项目 ${r} 不存在`},{status:404});return void 0!==u.mockingIntercept&&(e[r].mockingIntercept=u.mockingIntercept),void 0!==u.mockOpen&&(e[r].mockOpen=u.mockOpen),await (0,n.saveProjectsConfig)(e),s.NextResponse.json({success:!0,message:"项目配置更新成功",data:{projectName:r,mockingIntercept:e[r].mockingIntercept,mockOpen:e[r].mockOpen}})}if(!t||!i)return s.NextResponse.json({success:!1,error:"缺少必要参数:envName, newProxy"},{status:400});let p=await (0,n.getProjectsConfig)();if(!p[r])return s.NextResponse.json({success:!1,error:`项目 ${r} 不存在`},{status:404});if(!p[r].envs[t])return s.NextResponse.json({success:!1,error:`项目 ${r} 中不存在环境 ${t}`},{status:404});let l=p[r].envs[t];if("custom"===i){if(!a||""===a.trim())return s.NextResponse.json({success:!1,error:"选择 custom 时必须提供自定义代理地址"},{status:400})}else if(!l.proxyEnv[i])return s.NextResponse.json({success:!1,error:`代理环境 ${i} 不在可选范围内`},{status:400});p[r].envs[t].currentProxy=i,"custom"===i&&void 0!==a&&(p[r].envs[t].proxyEnv.custom=a),await (0,n.saveProjectsConfig)(p);let m=await (0,o.updateProjectEnvFile)(r,t,p[r],c.WORKSPACE_CONFIG.WORKSPACE_ROOT),x={projectName:r,envName:t,currentProxy:p[r].envs[t].currentProxy,currentProxyUrl:"custom"===i?a:l.proxyEnv[i]};if(!m.success)return console.warn(`环境文件更新失败: ${m.error}`),s.NextResponse.json({success:!0,message:"代理环境更新成功,但环境文件更新失败",warning:`环境文件更新失败: ${m.error}`,data:x});return s.NextResponse.json({success:!0,message:"代理环境更新成功",data:{...x,updatedEnvFile:m.updatedFile}})}catch(r){let e=r instanceof Error?r.message:"更新项目配置失败";return console.error("更新项目配置失败:",r),s.NextResponse.json({success:!1,error:e},{status:500})}}},42106:e=>{"use strict";var{g:r,__dirname:t}=e;{e.s({patchFetch:()=>i,routeModule:()=>r,serverHooks:()=>u,workAsyncStorage:()=>t,workUnitAsyncStorage:()=>a});var s=e.i(45746),n=e.i(93828),o=e.i(18250),c=e.i(32875);let r=new s.AppRouteRouteModule({definition:{kind:n.RouteKind.APP_ROUTE,page:"/api/project-config/route",pathname:"/api/project-config",filename:"route",bundlePath:""},resolvedPagePath:"[project]/packages/server/src/app/api/project-config/route.ts",nextConfigOutput:"",userland:c}),{workAsyncStorage:t,workUnitAsyncStorage:a,serverHooks:u}=r;function i(){return(0,o.patchFetch)({workAsyncStorage:t,workUnitAsyncStorage:a})}}}};
|
|
2
2
|
|
|
3
|
-
//# sourceMappingURL=%5Broot-of-the-server%
|
|
3
|
+
//# sourceMappingURL=%5Broot-of-the-server%5D__933f7077._.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["turbopack:///[project]/packages/server/src/lib/workspace-config.ts","turbopack:///[project]/packages/server/src/lib/workspace-types.ts","turbopack:///[project]/packages/server/src/lib/env-file-operations.ts","turbopack:///[project]/packages/server/src/app/api/project-config/route.ts","turbopack:///[project]/node_modules/.pnpm/next@15.3.4_react-dom@19.1.0_react@19.1.0__react@19.1.0/node_modules/next/dist/src/build/templates/app-route.ts"],"sourcesContent":["import { readFile, writeFile, access, constants, rename } from 'fs/promises';\nimport type { ProjectsConfig } from './workspace-types';\nimport { PROJECT_CONFIG_PATH } from './workspace-types';\n\n/**\n * 读取并解析项目配置文件\n * @returns {Promise<ProjectsConfig>} 项目配置对象\n */\nexport async function getProjectsConfig(): Promise<ProjectsConfig> {\n try {\n await access(PROJECT_CONFIG_PATH, constants.F_OK);\n } catch {\n // 文件不存在,创建并写入空对象\n await saveProjectsConfig({});\n return {};\n }\n\n try {\n const configContent = await readFile(PROJECT_CONFIG_PATH, 'utf-8');\n // 如果文件为空,返回空对象\n if (!configContent) {\n return {};\n }\n return JSON.parse(configContent);\n } catch (error) {\n console.error('读取或解析项目配置文件失败:', error);\n // 在出错时返回空对象或抛出错误,这里选择抛出以通知调用者\n throw new Error('无法加载项目配置');\n }\n}\n\n/**\n * 将项目配置写入文件(原子操作)\n * @param {ProjectsConfig} config - 要保存的配置对象\n */\nexport async function saveProjectsConfig(config: ProjectsConfig): Promise<void> {\n const tempConfigPath = PROJECT_CONFIG_PATH + '.tmp';\n try {\n await writeFile(tempConfigPath, JSON.stringify(config, null, 2), 'utf-8');\n await rename(tempConfigPath, PROJECT_CONFIG_PATH);\n } catch (error) {\n console.error('保存项目配置文件失败:', error);\n throw new Error('无法保存项目配置');\n }\n}\n\n/**\n * 项目状态枚举\n */\nexport enum ProjectStatus {\n PENDING = 'pending',\n EXISTING = 'existing',\n CLONING = 'cloning',\n SUCCESS = 'success',\n FAILED = 'failed',\n RETRYING = 'retrying',\n}\n\n/**\n * 项目进度信息接口\n */\nexport interface ProjectProgress {\n projectName: string;\n status: ProjectStatus;\n progress: number; // 0-100\n message: string;\n error?: string;\n startTime?: number;\n endTime?: number;\n}\n\n/**\n * 初始化结果接口\n */\nexport interface InitializationResult {\n success: boolean;\n totalProjects: number;\n successCount: number;\n failedCount: number;\n failedProjects: string[];\n workspacePath: string;\n duration: number;\n}\n\n/**\n * Git 操作配置接口\n */\nexport interface GitOperationConfig {\n repoUrl: string;\n targetDir: string;\n timeout: number;\n onProgress?: (progress: number, message: string) => void;\n onError?: (error: string) => void;\n}","import { homedir, cpus } from 'os';\nimport { join } from 'path';\n\n/**\n * 工作空间配置常量\n */\nexport const WORKSPACE_CONFIG = {\n // 工作空间根目录路径\n WORKSPACE_ROOT: join(homedir(), 'Documents', 'prime-workspace'),\n\n // Git 操作超时时间 (毫秒)\n GIT_TIMEOUT: 300000, // 5分钟\n\n // 最大并发克隆数量(基于CPU核心数,最小2个,最大8个)\n MAX_CONCURRENT_CLONES: Math.max(2, Math.min(cpus().length, 8)),\n\n // 重试次数限制\n MAX_RETRY_ATTEMPTS: 3,\n} as const;\n\nexport const PROJECT_CONFIG_PATH = join(homedir(), '.prime-projects.json');\n\nexport interface ProjectConfig {\n repo: string;\n mockingIntercept?: boolean;\n mockOpen?: boolean;\n envs: {\n [envName: string]: {\n host: string;\n currentProxy: string;\n proxyEnv: {\n [key: string]: string;\n };\n envFileName: string;\n proxyKey: string;\n subApps?: string[];\n };\n };\n}\n\nexport interface ProjectsConfig {\n [projectName: string]: ProjectConfig;\n}\n\n/**\n * 项目状态枚举\n */\nexport enum ProjectStatus {\n PENDING = 'pending',\n EXISTING = 'existing',\n CLONING = 'cloning',\n SUCCESS = 'success',\n FAILED = 'failed',\n RETRYING = 'retrying',\n INCOMPLETE = 'incomplete', // 不完整的项目,需要清理\n}\n\n/**\n * 项目进度信息接口\n */\nexport interface ProjectProgress {\n projectName: string;\n status: ProjectStatus;\n progress: number; // 0-100\n message: string;\n error?: string;\n startTime?: number;\n endTime?: number;\n}\n\n/**\n * 初始化结果接口\n */\nexport interface InitializationResult {\n success: boolean;\n totalProjects: number;\n successCount: number;\n failedCount: number;\n failedProjects: string[];\n workspacePath: string;\n duration: number;\n}\n\n/**\n * Git 操作配置接口\n */\nexport interface GitOperationConfig {\n repoUrl: string;\n targetDir: string;\n timeout: number;\n onProgress?: (progress: number, message: string) => void;\n onError?: (error: string) => void;\n onLog?: (projectName: string, logType: 'stdout' | 'stderr' | 'progress', content: string) => void;\n} ","import { promises as fs } from 'fs';\nimport { join } from 'path';\nimport type { ProjectConfig } from './workspace-types';\n\n/**\n * 为指定项目创建环境文件,如果文件已存在则跳过。\n * @param projectName - 项目名称\n * @param projectConfig - 项目配置\n * @param workspacePath - 工作空间根路径\n * @returns 一个包含已创建和已跳过文件列表的对象\n */\nexport async function createProjectEnvFiles(\n projectName: string,\n projectConfig: ProjectConfig,\n workspacePath: string,\n): Promise<{\n success: boolean;\n createdFiles: string[];\n skippedFiles: string[];\n error?: string;\n}> {\n const projectPath = join(workspacePath, projectName);\n const createdFiles: string[] = [];\n const skippedFiles: string[] = [];\n\n try {\n const envs = projectConfig.envs || {};\n for (const envName in envs) {\n const envConfig = envs[envName];\n if (envConfig.envFileName && envConfig.proxyKey) {\n const filePath = join(projectPath, envConfig.envFileName);\n \n try {\n await fs.access(filePath);\n // 文件已存在,跳过\n skippedFiles.push(envConfig.envFileName);\n } catch {\n // 文件不存在,创建它\n const currentProxyUrl = envConfig.proxyEnv[envConfig.currentProxy] || '';\n const content = `${envConfig.proxyKey}=${currentProxyUrl}`;\n await fs.writeFile(filePath, content, 'utf-8');\n createdFiles.push(envConfig.envFileName);\n }\n }\n }\n return { success: true, createdFiles, skippedFiles };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.error(`在为项目 ${projectName} 创建环境文件时出错:`, error);\n return { success: false, createdFiles, skippedFiles, error: errorMessage };\n }\n}\n\n/**\n * 为指定项目创建.mock文件夹\n * @param projectName - 项目名称\n * @param workspacePath - 工作空间根路径\n * @returns 创建结果\n */\nexport async function createProjectMockDirectories(\n projectName: string,\n workspacePath: string,\n): Promise<{\n success: boolean;\n createdDirectories: string[];\n skippedDirectories: string[];\n error?: string;\n}> {\n const projectPath = join(workspacePath, projectName);\n const mockPath = join(projectPath, '.mock');\n const createdDirectories: string[] = [];\n const skippedDirectories: string[] = [];\n\n try {\n // 创建 .mock 文件夹\n try {\n await fs.access(mockPath);\n skippedDirectories.push('.mock');\n } catch {\n await fs.mkdir(mockPath, { recursive: true });\n createdDirectories.push('.mock');\n }\n\n return { success: true, createdDirectories, skippedDirectories };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.error(`在为项目 ${projectName} 创建Mock目录时出错:`, error);\n return { success: false, createdDirectories, skippedDirectories, error: errorMessage };\n }\n}\n\n/**\n * 更新指定项目环境的环境文件内容\n * @param projectName - 项目名称\n * @param envName - 环境名称\n * @param projectConfig - 项目配置\n * @param workspacePath - 工作空间根路径\n * @returns 更新结果\n */\nexport async function updateProjectEnvFile(\n projectName: string,\n envName: string,\n projectConfig: ProjectConfig,\n workspacePath: string,\n): Promise<{\n success: boolean;\n updatedFile?: string;\n error?: string;\n}> {\n try {\n const envConfig = projectConfig.envs[envName];\n \n if (!envConfig) {\n return {\n success: false,\n error: `环境 ${envName} 不存在于项目 ${projectName} 配置中`,\n };\n }\n\n if (!envConfig.envFileName || !envConfig.proxyKey) {\n return {\n success: false,\n error: `环境 ${envName} 缺少 envFileName 或 proxyKey 配置`,\n };\n }\n\n const projectPath = join(workspacePath, projectName);\n const filePath = join(projectPath, envConfig.envFileName);\n \n // 获取当前代理URL\n const currentProxyUrl = envConfig.proxyEnv[envConfig.currentProxy] || envConfig.currentProxy;\n const content = `${envConfig.proxyKey}=${currentProxyUrl}`;\n \n // 写入文件内容\n await fs.writeFile(filePath, content, 'utf-8');\n \n console.log(`已更新环境文件: ${filePath}, 内容: ${content}`);\n \n return {\n success: true,\n updatedFile: envConfig.envFileName,\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.error(`更新项目 ${projectName} 环境 ${envName} 的环境文件时出错:`, error);\n return {\n success: false,\n error: errorMessage,\n };\n }\n} ","import { NextRequest, NextResponse } from 'next/server';\nimport {\n getProjectsConfig,\n saveProjectsConfig,\n} from '@/lib/workspace-config';\nimport { updateProjectEnvFile } from '@/lib/env-file-operations';\nimport { WORKSPACE_CONFIG } from '@/lib/workspace-types';\n\nexport async function GET(request: NextRequest) {\n try {\n const { searchParams } = new URL(request.url);\n const projectName = searchParams.get('project');\n\n if (!projectName) {\n return NextResponse.json(\n { success: false, error: '项目名称参数缺失' },\n { status: 400 },\n );\n }\n\n // 读取项目配置文件\n const projectsConfig = await getProjectsConfig();\n\n // 检查项目是否存在\n if (!projectsConfig[projectName]) {\n return NextResponse.json(\n { success: false, error: `项目 ${projectName} 不存在` },\n { status: 404 },\n );\n }\n\n const projectConfig = projectsConfig[projectName];\n\n return NextResponse.json({\n success: true,\n data: {\n projectName,\n repo: projectConfig.repo,\n mockingIntercept: projectConfig.mockingIntercept,\n mockOpen: projectConfig.mockOpen,\n envs: projectConfig.envs,\n },\n });\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : '获取项目配置失败';\n console.error('获取项目配置失败:', error);\n return NextResponse.json(\n { success: false, error: errorMessage },\n { status: 500 },\n );\n }\n}\n\nexport async function PUT(request: NextRequest) {\n try {\n // 解析请求体\n const { projectName, envName, newProxy, customProxyUrl, projectConfig } =\n await request.json();\n\n // 参数验证\n if (!projectName) {\n return NextResponse.json(\n {\n success: false,\n error: '缺少必要参数:projectName',\n },\n { status: 400 },\n );\n }\n\n // 如果是项目级配置更新\n if (projectConfig) {\n // 读取当前配置文件\n const projectsConfig = await getProjectsConfig();\n\n // 检查项目是否存在\n if (!projectsConfig[projectName]) {\n return NextResponse.json(\n { success: false, error: `项目 ${projectName} 不存在` },\n { status: 404 },\n );\n }\n\n // 更新项目级配置\n if (projectConfig.mockingIntercept !== undefined) {\n projectsConfig[projectName].mockingIntercept = projectConfig.mockingIntercept;\n }\n if (projectConfig.mockOpen !== undefined) {\n projectsConfig[projectName].mockOpen = projectConfig.mockOpen;\n }\n\n // 保存更新后的配置\n await saveProjectsConfig(projectsConfig);\n\n return NextResponse.json({\n success: true,\n message: '项目配置更新成功',\n data: {\n projectName,\n mockingIntercept: projectsConfig[projectName].mockingIntercept,\n mockOpen: projectsConfig[projectName].mockOpen,\n },\n });\n }\n\n // 环境级配置更新的参数验证\n if (!envName || !newProxy) {\n return NextResponse.json(\n {\n success: false,\n error: '缺少必要参数:envName, newProxy',\n },\n { status: 400 },\n );\n }\n\n // 读取当前配置文件\n const projectsConfig = await getProjectsConfig();\n\n // 检查项目是否存在\n if (!projectsConfig[projectName]) {\n return NextResponse.json(\n { success: false, error: `项目 ${projectName} 不存在` },\n { status: 404 },\n );\n }\n\n // 检查环境是否存在\n if (!projectsConfig[projectName].envs[envName]) {\n return NextResponse.json(\n {\n success: false,\n error: `项目 ${projectName} 中不存在环境 ${envName}`,\n },\n { status: 404 },\n );\n }\n\n const envConfig = projectsConfig[projectName].envs[envName];\n\n // 验证新的代理地址是否在可选范围内\n if (newProxy === 'custom') {\n // 对于 custom 选项,只有在自定义代理 URL 为空时才报错\n // 如果自定义地址与现有预设值相同,这是允许的\n if (!customProxyUrl || customProxyUrl.trim() === '') {\n return NextResponse.json(\n { success: false, error: '选择 custom 时必须提供自定义代理地址' },\n { status: 400 },\n );\n }\n } else {\n // 对于其他选项,检查是否存在于 proxyEnv 中\n if (!envConfig.proxyEnv[newProxy]) {\n return NextResponse.json(\n { success: false, error: `代理环境 ${newProxy} 不在可选范围内` },\n { status: 400 },\n );\n }\n }\n\n // 更新 currentProxy 字段\n projectsConfig[projectName].envs[envName].currentProxy = newProxy;\n\n // 如果选择的是 custom,需要更新 custom 字段的值\n if (newProxy === 'custom' && customProxyUrl !== undefined) {\n projectsConfig[projectName].envs[envName].proxyEnv.custom =\n customProxyUrl;\n }\n\n // 保存更新后的配置\n await saveProjectsConfig(projectsConfig);\n\n // 更新项目的环境文件\n const envFileResult = await updateProjectEnvFile(\n projectName,\n envName,\n projectsConfig[projectName],\n WORKSPACE_CONFIG.WORKSPACE_ROOT,\n );\n\n // 准备响应数据\n const responseData = {\n projectName,\n envName,\n currentProxy: projectsConfig[projectName].envs[envName].currentProxy,\n currentProxyUrl: newProxy === 'custom' ? customProxyUrl : envConfig.proxyEnv[newProxy],\n };\n\n // 如果环境文件更新失败,在响应中包含警告信息\n if (!envFileResult.success) {\n console.warn(`环境文件更新失败: ${envFileResult.error}`);\n return NextResponse.json({\n success: true,\n message: '代理环境更新成功,但环境文件更新失败',\n warning: `环境文件更新失败: ${envFileResult.error}`,\n data: responseData,\n });\n }\n\n return NextResponse.json({\n success: true,\n message: '代理环境更新成功',\n data: {\n ...responseData,\n updatedEnvFile: envFileResult.updatedFile,\n },\n });\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : '更新项目配置失败';\n console.error('更新项目配置失败:', error);\n return NextResponse.json(\n { success: false, error: errorMessage },\n { status: 500 },\n );\n }\n} ","import {\n AppRouteRouteModule,\n type AppRouteRouteModuleOptions,\n} from '../../server/route-modules/app-route/module.compiled'\nimport { RouteKind } from '../../server/route-kind'\nimport { patchFetch as _patchFetch } from '../../server/lib/patch-fetch'\n\nimport * as userland from 'VAR_USERLAND'\n\n// These are injected by the loader afterwards. This is injected as a variable\n// instead of a replacement because this could also be `undefined` instead of\n// an empty string.\ndeclare const nextConfigOutput: AppRouteRouteModuleOptions['nextConfigOutput']\n\n// We inject the nextConfigOutput here so that we can use them in the route\n// module.\n// INJECT:nextConfigOutput\n\nconst routeModule = new AppRouteRouteModule({\n definition: {\n kind: RouteKind.APP_ROUTE,\n page: 'VAR_DEFINITION_PAGE',\n pathname: 'VAR_DEFINITION_PATHNAME',\n filename: 'VAR_DEFINITION_FILENAME',\n bundlePath: 'VAR_DEFINITION_BUNDLE_PATH',\n },\n resolvedPagePath: 'VAR_RESOLVED_PAGE_PATH',\n nextConfigOutput,\n userland,\n})\n\n// Pull out the exports that we need to expose from the module. This should\n// be eliminated when we've moved the other routes to the new format. These\n// are used to hook into the route.\nconst { workAsyncStorage, workUnitAsyncStorage, serverHooks } = routeModule\n\nfunction patchFetch() {\n return _patchFetch({\n workAsyncStorage,\n workUnitAsyncStorage,\n })\n}\n\nexport {\n routeModule,\n workAsyncStorage,\n workUnitAsyncStorage,\n serverHooks,\n patchFetch,\n}\n"],"names":["AppRouteRouteModule","RouteKind","patchFetch","_patchFetch","userland","routeModule","definition","kind","APP_ROUTE","page","pathname","filename","bundlePath","resolvedPagePath","nextConfigOutput","workAsyncStorage","workUnitAsyncStorage","serverHooks"],"mappings":"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","ignoreList":[4]}
|
|
1
|
+
{"version":3,"sources":["turbopack:///[project]/packages/server/src/lib/workspace-config.ts","turbopack:///[project]/packages/server/src/lib/workspace-types.ts","turbopack:///[project]/packages/server/src/lib/env-file-operations.ts","turbopack:///[project]/packages/server/src/app/api/project-config/route.ts","turbopack:///[project]/node_modules/.pnpm/next@15.3.4_react-dom@19.1.0_react@19.1.0__react@19.1.0/node_modules/next/dist/src/build/templates/app-route.ts"],"sourcesContent":["import { readFile, writeFile, access, constants, rename } from 'fs/promises';\nimport type { ProjectsConfig } from './workspace-types';\nimport { PROJECT_CONFIG_PATH } from './workspace-types';\n\n/**\n * 读取并解析项目配置文件\n * @returns {Promise<ProjectsConfig>} 项目配置对象\n */\nexport async function getProjectsConfig(): Promise<ProjectsConfig> {\n try {\n await access(PROJECT_CONFIG_PATH, constants.F_OK);\n } catch {\n // 文件不存在,创建并写入空对象\n await saveProjectsConfig({});\n return {};\n }\n\n try {\n const configContent = await readFile(PROJECT_CONFIG_PATH, 'utf-8');\n // 如果文件为空,返回空对象\n if (!configContent) {\n return {};\n }\n return JSON.parse(configContent);\n } catch (error) {\n console.error('读取或解析项目配置文件失败:', error);\n // 在出错时返回空对象或抛出错误,这里选择抛出以通知调用者\n throw new Error('无法加载项目配置');\n }\n}\n\n/**\n * 将项目配置写入文件(原子操作)\n * @param {ProjectsConfig} config - 要保存的配置对象\n */\nexport async function saveProjectsConfig(config: ProjectsConfig): Promise<void> {\n const tempConfigPath = PROJECT_CONFIG_PATH + '.tmp';\n try {\n await writeFile(tempConfigPath, JSON.stringify(config, null, 2), 'utf-8');\n await rename(tempConfigPath, PROJECT_CONFIG_PATH);\n } catch (error) {\n console.error('保存项目配置文件失败:', error);\n throw new Error('无法保存项目配置');\n }\n}\n\n/**\n * 项目状态枚举\n */\nexport enum ProjectStatus {\n PENDING = 'pending',\n EXISTING = 'existing',\n CLONING = 'cloning',\n SUCCESS = 'success',\n FAILED = 'failed',\n RETRYING = 'retrying',\n}\n\n/**\n * 项目进度信息接口\n */\nexport interface ProjectProgress {\n projectName: string;\n status: ProjectStatus;\n progress: number; // 0-100\n message: string;\n error?: string;\n startTime?: number;\n endTime?: number;\n}\n\n/**\n * 初始化结果接口\n */\nexport interface InitializationResult {\n success: boolean;\n totalProjects: number;\n successCount: number;\n failedCount: number;\n failedProjects: string[];\n workspacePath: string;\n duration: number;\n}\n\n/**\n * Git 操作配置接口\n */\nexport interface GitOperationConfig {\n repoUrl: string;\n targetDir: string;\n timeout: number;\n onProgress?: (progress: number, message: string) => void;\n onError?: (error: string) => void;\n}","import { homedir, cpus } from 'os';\nimport { join } from 'path';\n\n/**\n * 工作空间配置常量\n */\nexport const WORKSPACE_CONFIG = {\n // 工作空间根目录路径\n WORKSPACE_ROOT: join(homedir(), 'Documents', 'prime-workspace'),\n\n // Git 操作超时时间 (毫秒)\n GIT_TIMEOUT: 300000, // 5分钟\n\n // 最大并发克隆数量(基于CPU核心数,最小2个,最大8个)\n MAX_CONCURRENT_CLONES: Math.max(2, Math.min(cpus().length, 8)),\n\n // 重试次数限制\n MAX_RETRY_ATTEMPTS: 3,\n} as const;\n\nexport const PROJECT_CONFIG_PATH = join(homedir(), '.prime-projects.json');\n\nexport interface ProjectConfig {\n repo: string;\n mockingIntercept?: boolean;\n mockOpen?: boolean;\n envs: {\n [envName: string]: {\n host: string;\n currentProxy: string;\n proxyEnv: {\n [key: string]: string;\n };\n envFileName: string;\n proxyKey: string;\n subApps?: string[];\n };\n };\n}\n\nexport interface ProjectsConfig {\n [projectName: string]: ProjectConfig;\n}\n\n/**\n * 项目状态枚举\n */\nexport enum ProjectStatus {\n PENDING = 'pending',\n EXISTING = 'existing',\n CLONING = 'cloning',\n SUCCESS = 'success',\n FAILED = 'failed',\n RETRYING = 'retrying',\n INCOMPLETE = 'incomplete', // 不完整的项目,需要清理\n}\n\n/**\n * 项目进度信息接口\n */\nexport interface ProjectProgress {\n projectName: string;\n status: ProjectStatus;\n progress: number; // 0-100\n message: string;\n error?: string;\n startTime?: number;\n endTime?: number;\n}\n\n/**\n * 初始化结果接口\n */\nexport interface InitializationResult {\n success: boolean;\n totalProjects: number;\n successCount: number;\n failedCount: number;\n failedProjects: string[];\n workspacePath: string;\n duration: number;\n}\n\n/**\n * Git 操作配置接口\n */\nexport interface GitOperationConfig {\n repoUrl: string;\n targetDir: string;\n timeout: number;\n onProgress?: (progress: number, message: string) => void;\n onError?: (error: string) => void;\n onLog?: (projectName: string, logType: 'stdout' | 'stderr' | 'progress', content: string) => void;\n} ","import { promises as fs } from 'fs';\nimport { join } from 'path';\nimport type { ProjectConfig } from './workspace-types';\n\n/**\n * 为指定项目创建环境文件,如果文件已存在则跳过。\n * @param projectName - 项目名称\n * @param projectConfig - 项目配置\n * @param workspacePath - 工作空间根路径\n * @returns 一个包含已创建和已跳过文件列表的对象\n */\nexport async function createProjectEnvFiles(\n projectName: string,\n projectConfig: ProjectConfig,\n workspacePath: string,\n): Promise<{\n success: boolean;\n createdFiles: string[];\n skippedFiles: string[];\n error?: string;\n}> {\n const projectPath = join(workspacePath, projectName);\n const createdFiles: string[] = [];\n const skippedFiles: string[] = [];\n\n try {\n const envs = projectConfig.envs || {};\n for (const envName in envs) {\n const envConfig = envs[envName];\n if (envConfig.envFileName && envConfig.proxyKey) {\n const filePath = join(projectPath, envConfig.envFileName);\n \n try {\n await fs.access(filePath);\n // 文件已存在,跳过\n skippedFiles.push(envConfig.envFileName);\n } catch {\n // 文件不存在,创建它\n const currentProxyUrl = envConfig.proxyEnv[envConfig.currentProxy] || '';\n const content = `${envConfig.proxyKey}=${currentProxyUrl}`;\n await fs.writeFile(filePath, content, 'utf-8');\n createdFiles.push(envConfig.envFileName);\n }\n }\n }\n return { success: true, createdFiles, skippedFiles };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.error(`在为项目 ${projectName} 创建环境文件时出错:`, error);\n return { success: false, createdFiles, skippedFiles, error: errorMessage };\n }\n}\n\n/**\n * 为指定项目创建.mock文件夹\n * @param projectName - 项目名称\n * @param workspacePath - 工作空间根路径\n * @returns 创建结果\n */\nexport async function createProjectMockDirectories(\n projectName: string,\n workspacePath: string,\n): Promise<{\n success: boolean;\n createdDirectories: string[];\n skippedDirectories: string[];\n error?: string;\n}> {\n const projectPath = join(workspacePath, projectName);\n const mockPath = join(projectPath, '.mock');\n const createdDirectories: string[] = [];\n const skippedDirectories: string[] = [];\n\n try {\n // 创建 .mock 文件夹\n try {\n await fs.access(mockPath);\n skippedDirectories.push('.mock');\n } catch {\n await fs.mkdir(mockPath, { recursive: true });\n createdDirectories.push('.mock');\n }\n\n return { success: true, createdDirectories, skippedDirectories };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.error(`在为项目 ${projectName} 创建Mock目录时出错:`, error);\n return { success: false, createdDirectories, skippedDirectories, error: errorMessage };\n }\n}\n\n/**\n * 更新指定项目环境的环境文件内容\n * @param projectName - 项目名称\n * @param envName - 环境名称\n * @param projectConfig - 项目配置\n * @param workspacePath - 工作空间根路径\n * @returns 更新结果\n */\nexport async function updateProjectEnvFile(\n projectName: string,\n envName: string,\n projectConfig: ProjectConfig,\n workspacePath: string,\n): Promise<{\n success: boolean;\n updatedFile?: string;\n error?: string;\n}> {\n try {\n const envConfig = projectConfig.envs[envName];\n \n if (!envConfig) {\n return {\n success: false,\n error: `环境 ${envName} 不存在于项目 ${projectName} 配置中`,\n };\n }\n\n if (!envConfig.envFileName || !envConfig.proxyKey) {\n return {\n success: false,\n error: `环境 ${envName} 缺少 envFileName 或 proxyKey 配置`,\n };\n }\n\n const projectPath = join(workspacePath, projectName);\n const filePath = join(projectPath, envConfig.envFileName);\n \n // 获取当前代理URL\n const currentProxyUrl = envConfig.proxyEnv[envConfig.currentProxy] || envConfig.currentProxy;\n const content = `${envConfig.proxyKey}=${currentProxyUrl}`;\n \n // 写入文件内容\n await fs.writeFile(filePath, content, 'utf-8');\n \n console.log(`已更新环境文件: ${filePath}, 内容: ${content}`);\n \n return {\n success: true,\n updatedFile: envConfig.envFileName,\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.error(`更新项目 ${projectName} 环境 ${envName} 的环境文件时出错:`, error);\n return {\n success: false,\n error: errorMessage,\n };\n }\n} ","import { NextRequest, NextResponse } from 'next/server';\nimport {\n getProjectsConfig,\n saveProjectsConfig,\n} from '@/lib/workspace-config';\nimport { updateProjectEnvFile } from '@/lib/env-file-operations';\nimport { WORKSPACE_CONFIG } from '@/lib/workspace-types';\n\nexport async function GET(request: NextRequest) {\n try {\n const { searchParams } = new URL(request.url);\n const projectName = searchParams.get('project');\n\n if (!projectName) {\n return NextResponse.json(\n { success: false, error: '项目名称参数缺失' },\n { status: 400 },\n );\n }\n\n // 读取项目配置文件\n const projectsConfig = await getProjectsConfig();\n\n // 检查项目是否存在\n if (!projectsConfig[projectName]) {\n return NextResponse.json(\n { success: false, error: `项目 ${projectName} 不存在` },\n { status: 404 },\n );\n }\n\n const projectConfig = projectsConfig[projectName];\n\n return NextResponse.json({\n success: true,\n data: {\n projectName,\n repo: projectConfig.repo,\n mockingIntercept: projectConfig.mockingIntercept,\n mockOpen: projectConfig.mockOpen,\n envs: projectConfig.envs,\n },\n });\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : '获取项目配置失败';\n console.error('获取项目配置失败:', error);\n return NextResponse.json(\n { success: false, error: errorMessage },\n { status: 500 },\n );\n }\n}\n\nexport async function PUT(request: NextRequest) {\n try {\n // 解析请求体\n const { projectName, envName, newProxy, customProxyUrl, projectConfig } =\n await request.json();\n\n // 参数验证\n if (!projectName) {\n return NextResponse.json(\n {\n success: false,\n error: '缺少必要参数:projectName',\n },\n { status: 400 },\n );\n }\n\n // 如果是项目级配置更新\n if (projectConfig) {\n // 读取当前配置文件\n const projectsConfig = await getProjectsConfig();\n\n // 检查项目是否存在\n if (!projectsConfig[projectName]) {\n return NextResponse.json(\n { success: false, error: `项目 ${projectName} 不存在` },\n { status: 404 },\n );\n }\n\n // 更新项目级配置\n if (projectConfig.mockingIntercept !== undefined) {\n projectsConfig[projectName].mockingIntercept = projectConfig.mockingIntercept;\n }\n if (projectConfig.mockOpen !== undefined) {\n projectsConfig[projectName].mockOpen = projectConfig.mockOpen;\n }\n\n // 保存更新后的配置\n await saveProjectsConfig(projectsConfig);\n\n return NextResponse.json({\n success: true,\n message: '项目配置更新成功',\n data: {\n projectName,\n mockingIntercept: projectsConfig[projectName].mockingIntercept,\n mockOpen: projectsConfig[projectName].mockOpen,\n },\n });\n }\n\n // 环境级配置更新的参数验证\n if (!envName || !newProxy) {\n return NextResponse.json(\n {\n success: false,\n error: '缺少必要参数:envName, newProxy',\n },\n { status: 400 },\n );\n }\n\n // 读取当前配置文件\n const projectsConfig = await getProjectsConfig();\n\n // 检查项目是否存在\n if (!projectsConfig[projectName]) {\n return NextResponse.json(\n { success: false, error: `项目 ${projectName} 不存在` },\n { status: 404 },\n );\n }\n\n // 检查环境是否存在\n if (!projectsConfig[projectName].envs[envName]) {\n return NextResponse.json(\n {\n success: false,\n error: `项目 ${projectName} 中不存在环境 ${envName}`,\n },\n { status: 404 },\n );\n }\n\n const envConfig = projectsConfig[projectName].envs[envName];\n\n // 验证新的代理地址是否在可选范围内\n if (newProxy === 'custom') {\n // 对于 custom 选项,只有在自定义代理 URL 为空时才报错\n // 如果自定义地址与现有预设值相同,这是允许的\n if (!customProxyUrl || customProxyUrl.trim() === '') {\n return NextResponse.json(\n { success: false, error: '选择 custom 时必须提供自定义代理地址' },\n { status: 400 },\n );\n }\n } else {\n // 对于其他选项,检查是否存在于 proxyEnv 中\n if (!envConfig.proxyEnv[newProxy]) {\n return NextResponse.json(\n { success: false, error: `代理环境 ${newProxy} 不在可选范围内` },\n { status: 400 },\n );\n }\n }\n\n // 更新 currentProxy 字段\n projectsConfig[projectName].envs[envName].currentProxy = newProxy;\n\n // 如果选择的是 custom,需要更新 custom 字段的值\n if (newProxy === 'custom' && customProxyUrl !== undefined) {\n projectsConfig[projectName].envs[envName].proxyEnv.custom =\n customProxyUrl;\n }\n\n // 保存更新后的配置\n await saveProjectsConfig(projectsConfig);\n\n // 更新项目的环境文件\n const envFileResult = await updateProjectEnvFile(\n projectName,\n envName,\n projectsConfig[projectName],\n WORKSPACE_CONFIG.WORKSPACE_ROOT,\n );\n\n // 准备响应数据\n const responseData = {\n projectName,\n envName,\n currentProxy: projectsConfig[projectName].envs[envName].currentProxy,\n currentProxyUrl: newProxy === 'custom' ? customProxyUrl : envConfig.proxyEnv[newProxy],\n };\n\n // 如果环境文件更新失败,在响应中包含警告信息\n if (!envFileResult.success) {\n console.warn(`环境文件更新失败: ${envFileResult.error}`);\n return NextResponse.json({\n success: true,\n message: '代理环境更新成功,但环境文件更新失败',\n warning: `环境文件更新失败: ${envFileResult.error}`,\n data: responseData,\n });\n }\n\n return NextResponse.json({\n success: true,\n message: '代理环境更新成功',\n data: {\n ...responseData,\n updatedEnvFile: envFileResult.updatedFile,\n },\n });\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : '更新项目配置失败';\n console.error('更新项目配置失败:', error);\n return NextResponse.json(\n { success: false, error: errorMessage },\n { status: 500 },\n );\n }\n} ","import {\n AppRouteRouteModule,\n type AppRouteRouteModuleOptions,\n} from '../../server/route-modules/app-route/module.compiled'\nimport { RouteKind } from '../../server/route-kind'\nimport { patchFetch as _patchFetch } from '../../server/lib/patch-fetch'\n\nimport * as userland from 'VAR_USERLAND'\n\n// These are injected by the loader afterwards. This is injected as a variable\n// instead of a replacement because this could also be `undefined` instead of\n// an empty string.\ndeclare const nextConfigOutput: AppRouteRouteModuleOptions['nextConfigOutput']\n\n// We inject the nextConfigOutput here so that we can use them in the route\n// module.\n// INJECT:nextConfigOutput\n\nconst routeModule = new AppRouteRouteModule({\n definition: {\n kind: RouteKind.APP_ROUTE,\n page: 'VAR_DEFINITION_PAGE',\n pathname: 'VAR_DEFINITION_PATHNAME',\n filename: 'VAR_DEFINITION_FILENAME',\n bundlePath: 'VAR_DEFINITION_BUNDLE_PATH',\n },\n resolvedPagePath: 'VAR_RESOLVED_PAGE_PATH',\n nextConfigOutput,\n userland,\n})\n\n// Pull out the exports that we need to expose from the module. This should\n// be eliminated when we've moved the other routes to the new format. These\n// are used to hook into the route.\nconst { workAsyncStorage, workUnitAsyncStorage, serverHooks } = routeModule\n\nfunction patchFetch() {\n return _patchFetch({\n workAsyncStorage,\n workUnitAsyncStorage,\n })\n}\n\nexport {\n routeModule,\n workAsyncStorage,\n workUnitAsyncStorage,\n serverHooks,\n patchFetch,\n}\n"],"names":["AppRouteRouteModule","RouteKind","patchFetch","_patchFetch","userland","routeModule","definition","kind","APP_ROUTE","page","pathname","filename","bundlePath","resolvedPagePath","nextConfigOutput","workAsyncStorage","workUnitAsyncStorage","serverHooks"],"mappings":"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","ignoreList":[4]}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
module.exports={45935:function(e){var{g:r,__dirname:t,m:s,e:n}=e;s.exports=e.x("next/dist/server/app-render/after-task-async-storage.external.js",()=>require("next/dist/server/app-render/after-task-async-storage.external.js"))},29549:function(e){var{g:r,__dirname:t,m:s,e:n}=e;s.exports=e.x("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js",()=>require("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js"))},83943:function(e){var{g:r,__dirname:t,m:s,e:n}=e;s.exports=e.x("next/dist/server/app-render/work-unit-async-storage.external.js",()=>require("next/dist/server/app-render/work-unit-async-storage.external.js"))},86103:function(e){var{g:r,__dirname:t,m:s,e:n}=e;s.exports=e.x("next/dist/server/app-render/work-async-storage.external.js",()=>require("next/dist/server/app-render/work-async-storage.external.js"))},30331:function(e){var{g:r,__dirname:t,m:s,e:n}=e;s.exports=e.x("path",()=>require("path"))},23430:function(e){var{g:r,__dirname:t,m:s,e:n}=e;s.exports=e.x("next/dist/compiled/@opentelemetry/api",()=>require("next/dist/compiled/@opentelemetry/api"))},13442:function(e){var{g:r,__dirname:t,m:s,e:n}=e;s.exports=e.x("os",()=>require("os"))},52670:function(e){var{g:r,__dirname:t,m:s,e:n}=e;s.exports=e.x("next/dist/compiled/next-server/app-route-turbo.runtime.prod.js",()=>require("next/dist/compiled/next-server/app-route-turbo.runtime.prod.js"))},88941:e=>{"use strict";var{g:r,__dirname:t}=e;{e.s({PROJECT_CONFIG_PATH:()=>t,ProjectStatus:()=>o,WORKSPACE_CONFIG:()=>r});var s=e.i(13442),n=e.i(30331);let r={WORKSPACE_ROOT:(0,n.join)((0,s.homedir)(),"Documents","prime-workspace"),GIT_TIMEOUT:3e5,MAX_CONCURRENT_CLONES:Math.max(2,Math.min((0,s.cpus)().length,8)),MAX_RETRY_ATTEMPTS:3},t=(0,n.join)((0,s.homedir)(),".prime-projects.json");var o=function(e){return e.PENDING="pending",e.EXISTING="existing",e.CLONING="cloning",e.SUCCESS="success",e.FAILED="failed",e.RETRYING="retrying",e.INCOMPLETE="incomplete",e}({})}},83886:function(e){var{g:r,__dirname:t,m:s,e:n}=e;s.exports=e.x("fs",()=>require("fs"))},87485:function(e){var{g:r,__dirname:t,m:s,e:n}=e;s.exports=e.x("child_process",()=>require("child_process"))},80275:function(e){var{g:r,__dirname:t,m:s,e:n}=e},1163:e=>{"use strict";var{g:r,__dirname:t}=e;e.s({GET:()=>p});var s=e.i(15494),n=e.i(87485),o=e.i(30331),i=e.i(83886),a=e.i(88941);async function p(e){try{let{searchParams:r}=new URL(e.url),t=r.get("project");if(!t)return s.NextResponse.json({success:!1,error:"缺少项目名称参数"},{status:400});let n=a.WORKSPACE_CONFIG.WORKSPACE_ROOT,p=(0,o.join)(n,t);if(console.log("工作空间路径:",n),console.log("项目路径:",p),console.log("项目目录是否存在:",(0,i.existsSync)(p)),!(0,i.existsSync)(p))return s.NextResponse.json({success:!1,error:`项目目录不存在: ${p}`},{status:404});let u=(0,o.join)(p,".git");if(!(0,i.existsSync)(u))return s.NextResponse.json({success:!1,error:"该项目不是Git仓库"},{status:400});let d=await c(p);return s.NextResponse.json({success:!0,data:d})}catch(e){return console.error("获取分支信息失败:",e),s.NextResponse.json({success:!1,error:e instanceof Error?e.message:"获取分支信息失败"},{status:500})}}async function c(e){return new Promise((r,t)=>{let s=(0,n.spawn)("git",["branch","--show-current"],{cwd:e,stdio:["pipe","pipe","pipe"]}),o="",i="";s.stdout?.on("data",e=>{o+=e.toString()}),s.stderr?.on("data",e=>{i+=e.toString()}),s.on("close",async s=>{if(0!==s)return void t(Error(`获取分支名称失败: ${i}`));let n=o.trim();try{let[t,s]=await Promise.all([u(e),d(e)]);r({currentBranch:n,lastCommit:t,status:s})}catch(e){t(e)}}),s.on("error",e=>{t(Error(`执行git命令失败: ${e.message}`))})})}async function u(e){return new Promise((r,t)=>{let s=(0,n.spawn)("git",["log","-1","--pretty=format:%H|%s|%an|%ad","--date=format:%Y-%m-%d %H:%M:%S"],{cwd:e,stdio:["pipe","pipe","pipe"]}),o="",i="";s.stdout?.on("data",e=>{o+=e.toString()}),s.stderr?.on("data",e=>{i+=e.toString()}),s.on("close",e=>{if(0!==e)return void t(Error(`获取提交信息失败: ${i}`));let s=o.trim().split("|");if(s.length<4)return void t(Error("提交信息格式错误"));r({hash:s[0].substring(0,8),message:s[1],author:s[2],date:s[3]})}),s.on("error",e=>{t(Error(`执行git log命令失败: ${e.message}`))})})}async function d(e){return new Promise((r,t)=>{let s=(0,n.spawn)("git",["status","--porcelain","-b"],{cwd:e,stdio:["pipe","pipe","pipe"]}),o="",i="";s.stdout?.on("data",e=>{o+=e.toString()}),s.stderr?.on("data",e=>{i+=e.toString()}),s.on("close",e=>{if(0!==e)return void t(Error(`获取仓库状态失败: ${i}`));let s=o.trim().split("\n"),n=0,a=0,p=0,c=0,u=0;s.forEach(e=>{if(e.startsWith("##")){let r=e.match(/ahead (\d+)/),t=e.match(/behind (\d+)/);r&&(n=parseInt(r[1],10)),t&&(a=parseInt(t[1],10))}else if(e.length>=2){let r=e.substring(0,2);" "!==r[0]&&"?"!==r[0]&&c++," "!==r[1]&&"?"!==r[1]&&p++,"??"===r&&u++}}),r({ahead:n,behind:a,modified:p,staged:c,untracked:u})}),s.on("error",e=>{t(Error(`执行git status命令失败: ${e.message}`))})})}},96463:e=>{"use strict";var{g:r,__dirname:t}=e;{e.s({patchFetch:()=>a,routeModule:()=>r,serverHooks:()=>c,workAsyncStorage:()=>t,workUnitAsyncStorage:()=>p});var s=e.i(45746),n=e.i(93828),o=e.i(18250),i=e.i(1163);let r=new s.AppRouteRouteModule({definition:{kind:n.RouteKind.APP_ROUTE,page:"/api/current-branch/route",pathname:"/api/current-branch",filename:"route",bundlePath:""},resolvedPagePath:"[project]/packages/server/src/app/api/current-branch/route.ts",nextConfigOutput:"",userland:i}),{workAsyncStorage:t,workUnitAsyncStorage:p,serverHooks:c}=r;function a(){return(0,o.patchFetch)({workAsyncStorage:t,workUnitAsyncStorage:p})}}}};
|
|
2
|
+
|
|
3
|
+
//# sourceMappingURL=%5Broot-of-the-server%5D__94e10604._.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["turbopack:///[project]/packages/server/src/lib/workspace-types.ts","turbopack:///[project]/packages/server/src/app/api/current-branch/route.ts","turbopack:///[project]/node_modules/.pnpm/next@15.3.4_react-dom@19.1.0_react@19.1.0__react@19.1.0/node_modules/next/dist/src/build/templates/app-route.ts"],"sourcesContent":["import { homedir, cpus } from 'os';\nimport { join } from 'path';\n\n/**\n * 工作空间配置常量\n */\nexport const WORKSPACE_CONFIG = {\n // 工作空间根目录路径\n WORKSPACE_ROOT: join(homedir(), 'Documents', 'prime-workspace'),\n\n // Git 操作超时时间 (毫秒)\n GIT_TIMEOUT: 300000, // 5分钟\n\n // 最大并发克隆数量(基于CPU核心数,最小2个,最大8个)\n MAX_CONCURRENT_CLONES: Math.max(2, Math.min(cpus().length, 8)),\n\n // 重试次数限制\n MAX_RETRY_ATTEMPTS: 3,\n} as const;\n\nexport const PROJECT_CONFIG_PATH = join(homedir(), '.prime-projects.json');\n\nexport interface ProjectConfig {\n repo: string;\n mockingIntercept?: boolean;\n mockOpen?: boolean;\n envs: {\n [envName: string]: {\n host: string;\n currentProxy: string;\n proxyEnv: {\n [key: string]: string;\n };\n envFileName: string;\n proxyKey: string;\n subApps?: string[];\n };\n };\n}\n\nexport interface ProjectsConfig {\n [projectName: string]: ProjectConfig;\n}\n\n/**\n * 项目状态枚举\n */\nexport enum ProjectStatus {\n PENDING = 'pending',\n EXISTING = 'existing',\n CLONING = 'cloning',\n SUCCESS = 'success',\n FAILED = 'failed',\n RETRYING = 'retrying',\n INCOMPLETE = 'incomplete', // 不完整的项目,需要清理\n}\n\n/**\n * 项目进度信息接口\n */\nexport interface ProjectProgress {\n projectName: string;\n status: ProjectStatus;\n progress: number; // 0-100\n message: string;\n error?: string;\n startTime?: number;\n endTime?: number;\n}\n\n/**\n * 初始化结果接口\n */\nexport interface InitializationResult {\n success: boolean;\n totalProjects: number;\n successCount: number;\n failedCount: number;\n failedProjects: string[];\n workspacePath: string;\n duration: number;\n}\n\n/**\n * Git 操作配置接口\n */\nexport interface GitOperationConfig {\n repoUrl: string;\n targetDir: string;\n timeout: number;\n onProgress?: (progress: number, message: string) => void;\n onError?: (error: string) => void;\n onLog?: (projectName: string, logType: 'stdout' | 'stderr' | 'progress', content: string) => void;\n} ","import { NextRequest, NextResponse } from 'next/server';\nimport { spawn } from 'child_process';\nimport { join } from 'path';\nimport { existsSync } from 'fs';\nimport { WORKSPACE_CONFIG } from '@/lib/workspace-types';\n\n/**\n * 获取项目当前分支信息的API\n */\nexport async function GET(request: NextRequest) {\n try {\n const { searchParams } = new URL(request.url);\n const projectName = searchParams.get('project');\n\n if (!projectName) {\n return NextResponse.json({\n success: false,\n error: '缺少项目名称参数'\n }, { status: 400 });\n }\n\n // 使用工作空间配置路径\n const workspacePath = WORKSPACE_CONFIG.WORKSPACE_ROOT;\n const projectPath = join(workspacePath, projectName);\n\n console.log('工作空间路径:', workspacePath);\n console.log('项目路径:', projectPath);\n console.log('项目目录是否存在:', existsSync(projectPath));\n\n // 检查项目目录是否存在\n if (!existsSync(projectPath)) {\n return NextResponse.json({\n success: false,\n error: `项目目录不存在: ${projectPath}`\n }, { status: 404 });\n }\n\n // 检查是否为git仓库\n const gitPath = join(projectPath, '.git');\n if (!existsSync(gitPath)) {\n return NextResponse.json({\n success: false,\n error: '该项目不是Git仓库'\n }, { status: 400 });\n }\n\n // 获取当前分支信息\n const branchInfo = await getCurrentBranchInfo(projectPath);\n \n return NextResponse.json({\n success: true,\n data: branchInfo\n });\n\n } catch (error) {\n console.error('获取分支信息失败:', error);\n return NextResponse.json({\n success: false,\n error: error instanceof Error ? error.message : '获取分支信息失败'\n }, { status: 500 });\n }\n}\n\n/**\n * 获取当前分支详细信息\n */\nasync function getCurrentBranchInfo(projectPath: string): Promise<{\n currentBranch: string;\n lastCommit: {\n hash: string;\n message: string;\n author: string;\n date: string;\n };\n status: {\n ahead: number;\n behind: number;\n modified: number;\n staged: number;\n untracked: number;\n };\n}> {\n return new Promise((resolve, reject) => {\n // 获取当前分支名称\n const branchProcess = spawn('git', ['branch', '--show-current'], {\n cwd: projectPath,\n stdio: ['pipe', 'pipe', 'pipe']\n });\n\n let branchOutput = '';\n let branchError = '';\n\n branchProcess.stdout?.on('data', (data) => {\n branchOutput += data.toString();\n });\n\n branchProcess.stderr?.on('data', (data) => {\n branchError += data.toString();\n });\n\n branchProcess.on('close', async (code) => {\n if (code !== 0) {\n reject(new Error(`获取分支名称失败: ${branchError}`));\n return;\n }\n\n const currentBranch = branchOutput.trim();\n\n try {\n // 并行获取其他信息\n const [lastCommit, status] = await Promise.all([\n getLastCommitInfo(projectPath),\n getRepositoryStatus(projectPath)\n ]);\n\n resolve({\n currentBranch,\n lastCommit,\n status\n });\n } catch (error) {\n reject(error);\n }\n });\n\n branchProcess.on('error', (error) => {\n reject(new Error(`执行git命令失败: ${error.message}`));\n });\n });\n}\n\n/**\n * 获取最后一次提交信息\n */\nasync function getLastCommitInfo(projectPath: string): Promise<{\n hash: string;\n message: string;\n author: string;\n date: string;\n}> {\n return new Promise((resolve, reject) => {\n const commitProcess = spawn('git', [\n 'log', \n '-1', \n '--pretty=format:%H|%s|%an|%ad', \n '--date=format:%Y-%m-%d %H:%M:%S'\n ], {\n cwd: projectPath,\n stdio: ['pipe', 'pipe', 'pipe']\n });\n\n let output = '';\n let error = '';\n\n commitProcess.stdout?.on('data', (data) => {\n output += data.toString();\n });\n\n commitProcess.stderr?.on('data', (data) => {\n error += data.toString();\n });\n\n commitProcess.on('close', (code) => {\n if (code !== 0) {\n reject(new Error(`获取提交信息失败: ${error}`));\n return;\n }\n\n const parts = output.trim().split('|');\n if (parts.length < 4) {\n reject(new Error('提交信息格式错误'));\n return;\n }\n\n resolve({\n hash: parts[0].substring(0, 8), // 只取前8位\n message: parts[1],\n author: parts[2],\n date: parts[3]\n });\n });\n\n commitProcess.on('error', (error) => {\n reject(new Error(`执行git log命令失败: ${error.message}`));\n });\n });\n}\n\n/**\n * 获取仓库状态信息\n */\nasync function getRepositoryStatus(projectPath: string): Promise<{\n ahead: number;\n behind: number;\n modified: number;\n staged: number;\n untracked: number;\n}> {\n return new Promise((resolve, reject) => {\n // 获取与远程分支的差异\n const statusProcess = spawn('git', ['status', '--porcelain', '-b'], {\n cwd: projectPath,\n stdio: ['pipe', 'pipe', 'pipe']\n });\n\n let output = '';\n let error = '';\n\n statusProcess.stdout?.on('data', (data) => {\n output += data.toString();\n });\n\n statusProcess.stderr?.on('data', (data) => {\n error += data.toString();\n });\n\n statusProcess.on('close', (code) => {\n if (code !== 0) {\n reject(new Error(`获取仓库状态失败: ${error}`));\n return;\n }\n\n const lines = output.trim().split('\\n');\n let ahead = 0;\n let behind = 0;\n let modified = 0;\n let staged = 0;\n let untracked = 0;\n\n lines.forEach(line => {\n if (line.startsWith('##')) {\n // 分析分支状态行,格式如: ## main...origin/main [ahead 1, behind 2]\n const aheadMatch = line.match(/ahead (\\d+)/);\n const behindMatch = line.match(/behind (\\d+)/);\n \n if (aheadMatch) {\n ahead = parseInt(aheadMatch[1], 10);\n }\n if (behindMatch) {\n behind = parseInt(behindMatch[1], 10);\n }\n } else if (line.length >= 2) {\n const statusCode = line.substring(0, 2);\n \n // 分析文件状态\n if (statusCode[0] !== ' ' && statusCode[0] !== '?') {\n staged++;\n }\n if (statusCode[1] !== ' ' && statusCode[1] !== '?') {\n modified++;\n }\n if (statusCode === '??') {\n untracked++;\n }\n }\n });\n\n resolve({\n ahead,\n behind,\n modified,\n staged,\n untracked\n });\n });\n\n statusProcess.on('error', (error) => {\n reject(new Error(`执行git status命令失败: ${error.message}`));\n });\n });\n}\n","import {\n AppRouteRouteModule,\n type AppRouteRouteModuleOptions,\n} from '../../server/route-modules/app-route/module.compiled'\nimport { RouteKind } from '../../server/route-kind'\nimport { patchFetch as _patchFetch } from '../../server/lib/patch-fetch'\n\nimport * as userland from 'VAR_USERLAND'\n\n// These are injected by the loader afterwards. This is injected as a variable\n// instead of a replacement because this could also be `undefined` instead of\n// an empty string.\ndeclare const nextConfigOutput: AppRouteRouteModuleOptions['nextConfigOutput']\n\n// We inject the nextConfigOutput here so that we can use them in the route\n// module.\n// INJECT:nextConfigOutput\n\nconst routeModule = new AppRouteRouteModule({\n definition: {\n kind: RouteKind.APP_ROUTE,\n page: 'VAR_DEFINITION_PAGE',\n pathname: 'VAR_DEFINITION_PATHNAME',\n filename: 'VAR_DEFINITION_FILENAME',\n bundlePath: 'VAR_DEFINITION_BUNDLE_PATH',\n },\n resolvedPagePath: 'VAR_RESOLVED_PAGE_PATH',\n nextConfigOutput,\n userland,\n})\n\n// Pull out the exports that we need to expose from the module. This should\n// be eliminated when we've moved the other routes to the new format. These\n// are used to hook into the route.\nconst { workAsyncStorage, workUnitAsyncStorage, serverHooks } = routeModule\n\nfunction patchFetch() {\n return _patchFetch({\n workAsyncStorage,\n workUnitAsyncStorage,\n })\n}\n\nexport {\n routeModule,\n workAsyncStorage,\n workUnitAsyncStorage,\n serverHooks,\n patchFetch,\n}\n"],"names":["AppRouteRouteModule","RouteKind","patchFetch","_patchFetch","userland","routeModule","definition","kind","APP_ROUTE","page","pathname","filename","bundlePath","resolvedPagePath","nextConfigOutput","workAsyncStorage","workUnitAsyncStorage","serverHooks"],"mappings":"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","ignoreList":[2]}
|