prime-dev-cli 1.0.22 → 2.0.0
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 +2 -2
- package/dist/server/.next/build-manifest.json +2 -2
- package/dist/server/.next/cache/.rscinfo +1 -1
- 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 +2 -2
- 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.html +1 -1
- package/dist/server/.next/server/app/_not-found.rsc +1 -1
- package/dist/server/.next/server/app/api/admin-git-batch-create-branch/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/admin-git-batch-delete-branch/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/admin-git-batch-merge/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/check-workspace/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/gwh-git-flow/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-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/open-project/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.nft.json +1 -1
- package/dist/server/.next/server/app/api/uat-git-flow/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/uat-git-flow/step/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/configuration/page/app-build-manifest.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 +2 -2
- package/dist/server/.next/server/app/index.html +1 -1
- package/dist/server/.next/server/app/index.rsc +1 -1
- 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/chunks/[root-of-the-server]__0879b2d6._.js.map +1 -1
- package/dist/server/.next/server/chunks/[root-of-the-server]__0d56f35b._.js.map +1 -1
- package/dist/server/.next/server/chunks/[root-of-the-server]__0e8a08fc._.js.map +1 -1
- package/dist/server/.next/server/chunks/[root-of-the-server]__1e792460._.js.map +1 -1
- package/dist/server/.next/server/chunks/[root-of-the-server]__2a29597f._.js.map +1 -1
- package/dist/server/.next/server/chunks/[root-of-the-server]__2a78acef._.js.map +1 -1
- package/dist/server/.next/server/chunks/[root-of-the-server]__2f8b52da._.js.map +1 -1
- package/dist/server/.next/server/chunks/[root-of-the-server]__2ffbf0d3._.js +1 -1
- package/dist/server/.next/server/chunks/[root-of-the-server]__2ffbf0d3._.js.map +1 -1
- package/dist/server/.next/server/chunks/[root-of-the-server]__37bfbf6b._.js.map +1 -1
- package/dist/server/.next/server/chunks/[root-of-the-server]__452b5f9c._.js.map +1 -1
- package/dist/server/.next/server/chunks/[root-of-the-server]__4ec3205b._.js.map +1 -1
- package/dist/server/.next/server/chunks/[root-of-the-server]__4fd52ac1._.js.map +1 -1
- package/dist/server/.next/server/chunks/[root-of-the-server]__54f2f032._.js +3 -0
- package/dist/server/.next/server/chunks/[root-of-the-server]__54f2f032._.js.map +1 -0
- package/dist/server/.next/server/chunks/[root-of-the-server]__5c9f62f9._.js.map +1 -1
- package/dist/server/.next/server/chunks/[root-of-the-server]__66dc5e6b._.js.map +1 -1
- package/dist/server/.next/server/chunks/[root-of-the-server]__8637b7f1._.js.map +1 -1
- package/dist/server/.next/server/chunks/[root-of-the-server]__8a8561ea._.js.map +1 -1
- package/dist/server/.next/server/chunks/[root-of-the-server]__98088bea._.js +1 -1
- package/dist/server/.next/server/chunks/[root-of-the-server]__98088bea._.js.map +1 -1
- package/dist/server/.next/server/chunks/[root-of-the-server]__9e44bbc8._.js +20 -0
- package/dist/server/.next/server/chunks/[root-of-the-server]__9e44bbc8._.js.map +1 -0
- package/dist/server/.next/server/chunks/[root-of-the-server]__9f7a6c58._.js.map +1 -1
- package/dist/server/.next/server/chunks/[root-of-the-server]__a6fbefc6._.js.map +1 -1
- package/dist/server/.next/server/chunks/[root-of-the-server]__ac6efee1._.js.map +1 -1
- package/dist/server/.next/server/chunks/[root-of-the-server]__c18498ef._.js.map +1 -1
- package/dist/server/.next/server/chunks/[root-of-the-server]__c43cf810._.js +5 -0
- package/dist/server/.next/server/chunks/[root-of-the-server]__c43cf810._.js.map +1 -0
- package/dist/server/.next/server/chunks/[root-of-the-server]__dda45cac._.js.map +1 -1
- package/dist/server/.next/server/chunks/[root-of-the-server]__de18efbd._.js.map +1 -1
- package/dist/server/.next/server/chunks/[root-of-the-server]__e0b7050d._.js.map +1 -1
- package/dist/server/.next/server/chunks/[root-of-the-server]__ec681197._.js.map +1 -1
- package/dist/server/.next/server/chunks/[root-of-the-server]__f111df8e._.js.map +1 -1
- package/dist/server/.next/server/chunks/ssr/_5579d68f._.js +2 -2
- package/dist/server/.next/server/chunks/ssr/_5579d68f._.js.map +1 -1
- package/dist/server/.next/server/chunks/ssr/_b0947ff2._.js +1 -1
- package/dist/server/.next/server/chunks/ssr/_b0947ff2._.js.map +1 -1
- package/dist/server/.next/server/chunks/ssr/packages_server_src_7cef6dbd._.js.map +1 -1
- 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/server-reference-manifest.js +1 -1
- package/dist/server/.next/server/server-reference-manifest.json +1 -1
- package/dist/server/.next/static/chunks/{13acbe5989647429.js → 2d9a99312c08fbf9.js} +1 -1
- package/dist/server/.next/static/chunks/51208386dbc1874e.js.map +1 -0
- package/dist/server/.next/static/chunks/8c850efc5ffddd02.js +57 -0
- package/dist/server/.next/static/chunks/f36be6bae8f3723b.js.map +1 -0
- package/dist/server/.next/trace +2 -2
- package/package.json +1 -1
- package/dist/server/.next/server/chunks/[root-of-the-server]__a74239fc._.js +0 -3
- package/dist/server/.next/server/chunks/[root-of-the-server]__a74239fc._.js.map +0 -1
- package/dist/server/.next/server/chunks/[root-of-the-server]__aaa3fe74._.js +0 -5
- package/dist/server/.next/server/chunks/[root-of-the-server]__aaa3fe74._.js.map +0 -1
- package/dist/server/.next/server/chunks/[root-of-the-server]__b176e8df._.js +0 -20
- package/dist/server/.next/server/chunks/[root-of-the-server]__b176e8df._.js.map +0 -1
- package/dist/server/.next/static/chunks/205cbae70a6c50e1.js.map +0 -1
- package/dist/server/.next/static/chunks/2d2322acba49236a.js +0 -57
- package/dist/server/.next/static/chunks/f5014a46b22ea191.js.map +0 -1
- /package/dist/server/.next/static/{-cMGDUj-YvI_2FwzuOQqe → 4KbwlsFdd1vqSOg9Nuj9R}/_buildManifest.js +0 -0
- /package/dist/server/.next/static/{-cMGDUj-YvI_2FwzuOQqe → 4KbwlsFdd1vqSOg9Nuj9R}/_clientMiddlewareManifest.json +0 -0
- /package/dist/server/.next/static/{-cMGDUj-YvI_2FwzuOQqe → 4KbwlsFdd1vqSOg9Nuj9R}/_ssgManifest.js +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["turbopack:///[project]/packages/server/src/lib/workspace-types.ts","turbopack:///[project]/packages/server/src/lib/workspace-config.ts","turbopack:///[project]/packages/server/src/lib/log-manager.ts","turbopack:///[project]/packages/server/src/lib/process-monitor.ts","turbopack:///[project]/packages/server/src/app/api/process/start/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 projectName?: 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}\n","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 projectName?: string;\n targetDir: string;\n timeout: number;\n onProgress?: (progress: number, message: string) => void;\n onError?: (error: string) => void;\n}\n","/**\n * 日志管理器 - 处理日志文件的轮转、清理和大小限制\n */\nimport fs from 'fs/promises';\nimport path from 'path';\nimport os from 'os';\n\n// 日志配置\nconst LOG_CONFIG = {\n MAX_FILE_SIZE: 5 * 1024 * 1024, // 5MB\n MAX_LOG_FILES: 3, // 保留最多 3 个日志文件\n MAX_LOG_AGE_DAYS: 7, // 日志保留 7 天\n MAX_LINE_LENGTH: 1000, // 单行最大长度\n CLEANUP_INTERVAL: 30 * 60 * 1000, // 30 分钟清理一次\n};\n\n// 获取日志目录\nfunction getLogDir(): string {\n return path.join(os.homedir(), '.prime-process-logs');\n}\n\n// 获取进程日志文件路径\nexport function getProcessLogPath(processKey: string): string {\n return path.join(getLogDir(), `${processKey}.log`);\n}\n\n// 截断过长的日志行\nexport function truncateLogLine(line: string): string {\n if (line.length <= LOG_CONFIG.MAX_LINE_LENGTH) {\n return line;\n }\n return line.substring(0, LOG_CONFIG.MAX_LINE_LENGTH) + '... [truncated]';\n}\n\n/**\n * 获取文件大小\n */\nasync function getFileSize(filePath: string): Promise<number> {\n try {\n const stats = await fs.stat(filePath);\n return stats.size;\n } catch {\n return 0;\n }\n}\n\n/**\n * 轮转日志文件\n * 当日志文件超过大小限制时,将其重命名并创建新文件\n */\nexport async function rotateLogFile(processKey: string): Promise<void> {\n const logPath = getProcessLogPath(processKey);\n const fileSize = await getFileSize(logPath);\n\n // 如果文件大小未超过限制,不需要轮转\n if (fileSize < LOG_CONFIG.MAX_FILE_SIZE) {\n return;\n }\n\n console.log(`[日志管理] 轮转日志文件: ${processKey}, 大小: ${(fileSize / 1024 / 1024).toFixed(2)}MB`);\n\n try {\n // 删除最旧的日志文件\n const oldestLogPath = `${logPath}.${LOG_CONFIG.MAX_LOG_FILES}`;\n try {\n await fs.unlink(oldestLogPath);\n } catch {\n // 文件不存在,忽略\n }\n\n // 轮转现有的日志文件\n for (let i = LOG_CONFIG.MAX_LOG_FILES - 1; i >= 1; i--) {\n const oldPath = i === 1 ? logPath : `${logPath}.${i}`;\n const newPath = `${logPath}.${i + 1}`;\n\n try {\n await fs.rename(oldPath, newPath);\n } catch {\n // 文件不存在,继续\n }\n }\n\n // 重命名当前日志文件\n await fs.rename(logPath, `${logPath}.1`);\n\n // 创建新的空日志文件\n await fs.writeFile(logPath, '', 'utf-8');\n\n console.log(`[日志管理] 日志轮转完成: ${processKey}`);\n } catch (error) {\n console.error(`[日志管理] 轮转日志文件失败: ${processKey}`, error);\n }\n}\n\n/**\n * 追加日志到文件\n * 如果文件过大,先进行轮转\n */\nexport async function appendLog(processKey: string, logLine: string): Promise<void> {\n // 先检查是否需要轮转\n await rotateLogFile(processKey);\n\n const logPath = getProcessLogPath(processKey);\n const truncatedLine = truncateLogLine(logLine);\n\n try {\n // 确保日志目录存在\n await fs.mkdir(getLogDir(), { recursive: true });\n\n // 追加日志\n await fs.appendFile(logPath, truncatedLine + '\\n', 'utf-8');\n } catch (error) {\n console.error(`[日志管理] 追加日志失败: ${processKey}`, error);\n }\n}\n\n/**\n * 批量写入日志(用于初始写入或同步)\n */\nexport async function writeLogsSync(processKey: string, logs: string[]): Promise<void> {\n await rotateLogFile(processKey);\n\n const logPath = getProcessLogPath(processKey);\n const truncatedLogs = logs.map(line => truncateLogLine(line));\n\n try {\n await fs.mkdir(getLogDir(), { recursive: true });\n await fs.writeFile(logPath, truncatedLogs.join('\\n') + '\\n', 'utf-8');\n } catch (error) {\n console.error(`[日志管理] 写入日志失败: ${processKey}`, error);\n }\n}\n\n/**\n * 读取日志文件的最后 N 行\n */\nexport async function readLastNLines(processKey: string, n: number = 100): Promise<string[]> {\n const logPath = getProcessLogPath(processKey);\n\n try {\n const content = await fs.readFile(logPath, 'utf-8');\n const lines = content.split('\\n').filter(line => line.trim());\n return lines.slice(-n);\n } catch {\n return [];\n }\n}\n\n/**\n * 清理旧的日志文件\n * 删除超过保留期限的日志文件\n */\nexport async function cleanupOldLogs(): Promise<void> {\n console.log('[日志管理] 开始清理旧日志...');\n\n try {\n const logDir = getLogDir();\n\n // 确保目录存在\n try {\n await fs.access(logDir);\n } catch {\n console.log('[日志管理] 日志目录不存在,无需清理');\n return;\n }\n\n const files = await fs.readdir(logDir);\n const now = Date.now();\n const maxAge = LOG_CONFIG.MAX_LOG_AGE_DAYS * 24 * 60 * 60 * 1000;\n\n let deletedCount = 0;\n let freedSpace = 0;\n\n for (const file of files) {\n const filePath = path.join(logDir, file);\n\n try {\n const stats = await fs.stat(filePath);\n\n // 删除超过保留期的文件\n if (now - stats.mtime.getTime() > maxAge) {\n freedSpace += stats.size;\n try {\n await fs.unlink(filePath);\n deletedCount++;\n console.log(`[日志管理] 删除过期日志: ${file}`);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (unlinkError: any) {\n // 如果文件已经不存在,忽略错误\n if (unlinkError?.code !== 'ENOENT') {\n console.error(`[日志管理] 删除文件失败: ${file}`, unlinkError);\n }\n }\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (error: any) {\n // 如果文件不存在,跳过(可能已被删除)\n if (error?.code !== 'ENOENT') {\n console.error(`[日志管理] 处理文件失败: ${file}`, error);\n }\n }\n }\n\n console.log(`[日志管理] 清理完成: 删除 ${deletedCount} 个文件, 释放 ${(freedSpace / 1024 / 1024).toFixed(2)}MB`);\n } catch (error) {\n console.error('[日志管理] 清理日志失败:', error);\n }\n}\n\n/**\n * 删除指定进程的所有日志文件\n */\nexport async function deleteProcessLogs(processKey: string): Promise<void> {\n const logPath = getProcessLogPath(processKey);\n\n try {\n // 删除主日志文件\n await fs.unlink(logPath);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (error: any) {\n // 文件不存在,忽略\n if (error?.code !== 'ENOENT') {\n console.error(`[日志管理] 删除主日志文件失败: ${processKey}`, error);\n }\n }\n\n // 删除轮转的日志文件\n for (let i = 1; i <= LOG_CONFIG.MAX_LOG_FILES; i++) {\n try {\n await fs.unlink(`${logPath}.${i}`);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (error: any) {\n // 文件不存在,忽略\n if (error?.code !== 'ENOENT') {\n console.error(`[日志管理] 删除轮转日志文件失败: ${processKey}.${i}`, error);\n }\n }\n }\n\n console.log(`[日志管理] 删除进程日志: ${processKey}`);\n}\n\n/**\n * 获取日志目录的总大小\n */\nexport async function getLogsDirSize(): Promise<{ totalSize: number; fileCount: number }> {\n try {\n const logDir = getLogDir();\n const files = await fs.readdir(logDir);\n\n let totalSize = 0;\n let fileCount = 0;\n\n for (const file of files) {\n try {\n const stats = await fs.stat(path.join(logDir, file));\n totalSize += stats.size;\n fileCount++;\n } catch {\n // 忽略错误\n }\n }\n\n return { totalSize, fileCount };\n } catch {\n return { totalSize: 0, fileCount: 0 };\n }\n}\n\n// 定期清理任务\nlet cleanupTimer: NodeJS.Timeout | null = null;\n\n/**\n * 启动定期清理任务\n */\nexport function startLogCleanupTask(): void {\n if (cleanupTimer) {\n return; // 已经启动\n }\n\n console.log('[日志管理] 启动定期清理任务');\n\n // 立即执行一次\n cleanupOldLogs();\n\n // 设置定期清理\n cleanupTimer = setInterval(() => {\n cleanupOldLogs();\n }, LOG_CONFIG.CLEANUP_INTERVAL);\n}\n\n/**\n * 停止定期清理任务\n */\nexport function stopLogCleanupTask(): void {\n if (cleanupTimer) {\n clearInterval(cleanupTimer);\n cleanupTimer = null;\n console.log('[日志管理] 停止定期清理任务');\n }\n}\n\n// 进程退出时停止清理任务\nprocess.on('SIGINT', () => {\n stopLogCleanupTask();\n});\n\nprocess.on('SIGTERM', () => {\n stopLogCleanupTask();\n});\n\n","import fs from 'fs/promises';\nimport path from 'path';\nimport os from 'os';\nimport { exec } from 'child_process';\nimport { promisify } from 'util';\n\nconst execAsync = promisify(exec);\n\n// 进程信息接口\ninterface ProcessInfo {\n key: string;\n projectName: string;\n envName: string;\n pid: number;\n startTime: Date;\n port: string;\n}\n\n// 获取进程存储文件路径\nfunction getProcessStorePath() {\n return path.join(os.homedir(), '.prime-processes.json');\n}\n\n// 检查进程是否仍在运行\nasync function isProcessRunning(pid: number): Promise<boolean> {\n try {\n if (process.platform !== 'win32') {\n process.kill(pid, 0);\n return true;\n } else {\n const { stdout } = await execAsync(`tasklist /FI \"PID eq ${pid}\"`);\n return stdout.includes(pid.toString());\n }\n } catch {\n return false;\n }\n}\n\n// 加载并清理过期的进程信息\nexport async function loadAndCleanProcesses(): Promise<ProcessInfo[]> {\n try {\n const processInfoContent = await fs.readFile(getProcessStorePath(), 'utf-8');\n const processInfoList: ProcessInfo[] = JSON.parse(processInfoContent);\n \n // 过滤出仍在运行的进程\n const runningProcesses: ProcessInfo[] = [];\n \n for (const processInfo of processInfoList) {\n const isRunning = await isProcessRunning(processInfo.pid);\n if (isRunning) {\n runningProcesses.push(processInfo);\n }\n }\n \n // 如果有进程被清理,更新文件\n if (runningProcesses.length !== processInfoList.length) {\n await fs.writeFile(getProcessStorePath(), JSON.stringify(runningProcesses, null, 2));\n }\n \n return runningProcesses;\n } catch {\n // 文件不存在或解析错误,返回空数组\n return [];\n }\n}\n\n// 初始化进程监控 - 在应用启动时调用\nexport async function initializeProcessMonitoring() {\n console.log('初始化进程监控...');\n const processes = await loadAndCleanProcesses();\n console.log(`发现 ${processes.length} 个正在运行的进程`);\n return processes;\n}","import { NextRequest, NextResponse } from 'next/server';\nimport { spawn } from 'child_process';\nimport path from 'path';\nimport fs from 'fs/promises';\nimport os from 'os';\nimport { loadAndCleanProcesses } from '@/lib/process-monitor';\nimport { getProjectsConfig } from '@/lib/workspace-config';\nimport { WORKSPACE_CONFIG } from '@/lib/workspace-types';\nimport { \n appendLog, \n readLastNLines, \n deleteProcessLogs,\n startLogCleanupTask,\n truncateLogLine \n} from '@/lib/log-manager';\n\n// 存储进程信息的Map\ninterface ProcessData {\n process: {\n pid: number;\n killed: boolean;\n kill?: () => void;\n on?: (event: string, callback: (code?: number) => void) => void;\n };\n projectName: string;\n envName: string;\n startTime: Date;\n port: string;\n recentLogs: string[]; // 只保留最近的少量日志在内存中\n}\n\nconst processes = new Map<string, ProcessData>();\nconst MAX_MEMORY_LOG_LINES = 50; // 内存中只保留最近 50 行\n\n// 获取进程存储文件路径\nfunction getProcessStorePath() {\n return path.join(os.homedir(), '.prime-processes.json');\n}\n\n// 追加日志到文件和内存\nasync function logToFileAndMemory(processKey: string, logLine: string, processData: ProcessData) {\n // 截断过长的日志行\n const truncated = truncateLogLine(logLine);\n \n // 追加到文件(使用日志管理器,自动处理轮转)\n await appendLog(processKey, truncated);\n \n // 只在内存中保留最近的几条\n processData.recentLogs.push(truncated);\n if (processData.recentLogs.length > MAX_MEMORY_LOG_LINES) {\n processData.recentLogs.shift();\n }\n}\n\n// 保存进程信息到文件\nasync function saveProcessInfo() {\n const processInfo: {\n key: string;\n projectName: string;\n envName: string;\n startTime: Date;\n port: string;\n pid: number;\n }[] = [];\n processes.forEach((value, key) => {\n processInfo.push({\n key,\n projectName: value.projectName,\n envName: value.envName,\n startTime: value.startTime,\n port: value.port,\n pid: value.process.pid\n });\n });\n \n try {\n await fs.writeFile(getProcessStorePath(), JSON.stringify(processInfo, null, 2));\n } catch (error) {\n console.error('保存进程信息失败:', error);\n }\n}\n\n// 在启动时加载现有进程信息\nlet processesInitialized = false;\nasync function ensureProcessesLoaded() {\n if (!processesInitialized) {\n // 启动日志清理任务\n startLogCleanupTask();\n \n const existingProcesses = await loadAndCleanProcesses();\n for (const processInfo of existingProcesses) {\n // 恢复进程信息到内存,但不恢复实际的进程对象\n // 因为我们只需要知道进程存在,状态查询会检查实际的PID\n // 只加载最近的日志到内存\n const recentLogs = await readLastNLines(processInfo.key, MAX_MEMORY_LOG_LINES);\n \n processes.set(processInfo.key, {\n process: { pid: processInfo.pid, killed: false },\n projectName: processInfo.projectName,\n envName: processInfo.envName,\n startTime: new Date(processInfo.startTime),\n port: processInfo.port,\n recentLogs\n });\n }\n processesInitialized = true;\n }\n}\n\nexport async function POST(request: NextRequest) {\n await ensureProcessesLoaded();\n try {\n const { projectName, envName, startCommand } = await request.json();\n\n if (!projectName || !envName || !startCommand) {\n return NextResponse.json({\n success: false,\n error: '缺少必要参数'\n }, { status: 400 });\n }\n\n // 生成进程的唯一标识\n const processKey = `${projectName}-${envName}`;\n\n // 检查进程是否已经在运行\n if (processes.has(processKey)) {\n const existingProcess = processes.get(processKey);\n if (existingProcess && existingProcess.process && !existingProcess.process.killed) {\n return NextResponse.json({\n success: false,\n error: '该环境已经在运行中'\n }, { status: 400 });\n }\n }\n\n // 读取配置文件获取工作区路径\n const config = await getProjectsConfig();\n \n // 使用工作区常量路径\n const workspacePath = WORKSPACE_CONFIG.WORKSPACE_ROOT;\n \n // 构建项目路径\n const projectPath = path.join(workspacePath, projectName);\n\n // 检查项目目录是否存在\n try {\n await fs.access(projectPath);\n } catch {\n return NextResponse.json({\n success: false,\n error: '项目目录不存在'\n }, { status: 404 });\n }\n\n // 解析命令\n const [command, ...args] = startCommand.split(' ');\n\n // 启动进程 - 不传递 env 参数,让子进程继承父进程环境变量\n // 但通过环境变量覆盖确保开发模式\n const childProcess = spawn(command, args, {\n cwd: projectPath,\n shell: true,\n detached: false,\n stdio: ['ignore', 'pipe', 'pipe'],\n env: {\n ...process.env,\n NODE_ENV: 'development', // 强制设置为开发模式\n FORCE_COLOR: '1', // 保留颜色输出\n }\n });\n\n // 获取项目配置中的端口信息\n const projectConfig = config[projectName];\n const envConfig = projectConfig?.envs?.[envName];\n const port = envConfig?.host?.split(':').pop() || '';\n \n // 存储进程信息\n const processData: ProcessData = {\n process: {\n pid: childProcess.pid || 0,\n killed: false,\n kill: () => childProcess.kill(),\n on: (event: string, callback: (code?: number) => void) => {\n childProcess.on(event, callback);\n }\n },\n projectName,\n envName,\n startTime: new Date(),\n port,\n recentLogs: [] // 只在内存中保留最近的日志\n };\n \n processes.set(processKey, processData);\n \n // 捕获标准输出\n if (childProcess.stdout) {\n childProcess.stdout.on('data', async (data: Buffer) => {\n const text = data.toString();\n const lines = text.split('\\n');\n \n for (const line of lines) {\n // 过滤掉只包含控制序列的行\n const cleanedLine = line\n .replace(/\\x1b\\[[0-9;]*m/g, '') // 移除颜色代码\n .replace(/\\x1b\\[[0-9]*[A-Z]/g, '') // 移除光标控制\n .replace(/\\[\\d+[A-Z]/g, '') // 移除其他控制序列\n .trim();\n \n // 如果清理后的行不为空,则记录\n if (cleanedLine) {\n const logEntry = `[${new Date().toISOString()}] [STDOUT] ${line}`;\n await logToFileAndMemory(processKey, logEntry, processData);\n }\n }\n });\n }\n \n // 捕获标准错误\n if (childProcess.stderr) {\n childProcess.stderr.on('data', async (data: Buffer) => {\n const text = data.toString();\n const lines = text.split('\\n');\n \n for (const line of lines) {\n // 过滤掉只包含控制序列的行\n const cleanedLine = line\n .replace(/\\x1b\\[[0-9;]*m/g, '')\n .replace(/\\x1b\\[[0-9]*[A-Z]/g, '')\n .replace(/\\[\\d+[A-Z]/g, '')\n .trim();\n \n if (cleanedLine) {\n const logEntry = `[${new Date().toISOString()}] [STDERR] ${line}`;\n await logToFileAndMemory(processKey, logEntry, processData);\n }\n }\n });\n }\n\n // 保存进程信息到文件\n await saveProcessInfo();\n \n // 监听进程退出\n childProcess.on('exit', async (code) => {\n console.log(`进程 ${processKey} 退出,退出码: ${code}`);\n const logEntry = `[${new Date().toISOString()}] [SYSTEM] 进程退出,退出码: ${code}`;\n await appendLog(processKey, logEntry);\n \n processes.delete(processKey);\n await saveProcessInfo();\n });\n\n childProcess.on('error', (error) => {\n console.error(`进程 ${processKey} 错误:`, error);\n processes.delete(processKey);\n saveProcessInfo();\n });\n\n // 等待一小段时间确保进程启动\n await new Promise(resolve => setTimeout(resolve, 2000));\n\n // 检查进程是否仍在运行\n if (childProcess.killed) {\n processes.delete(processKey);\n await saveProcessInfo();\n return NextResponse.json({\n success: false,\n error: '进程启动失败'\n }, { status: 500 });\n }\n\n return NextResponse.json({\n success: true,\n data: {\n pid: childProcess.pid,\n startTime: new Date(),\n port\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// 停止进程\nexport async function DELETE(request: NextRequest) {\n await ensureProcessesLoaded();\n try {\n const { searchParams } = new URL(request.url);\n const projectName = searchParams.get('projectName');\n const envName = searchParams.get('envName');\n\n if (!projectName || !envName) {\n return NextResponse.json({\n success: false,\n error: '缺少必要参数'\n }, { status: 400 });\n }\n\n const processKey = `${projectName}-${envName}`;\n const processInfo = processes.get(processKey);\n\n if (!processInfo) {\n return NextResponse.json({\n success: false,\n error: '进程未找到'\n }, { status: 404 });\n }\n\n try {\n // 尝试优雅地终止进程\n process.kill(processInfo.process.pid, 'SIGTERM');\n \n // 给进程一些时间来清理\n await new Promise(resolve => setTimeout(resolve, 1000));\n \n // 如果进程仍在运行,强制终止\n try {\n process.kill(processInfo.process.pid, 0); // 检查进程是否存在\n process.kill(processInfo.process.pid, 'SIGKILL');\n } catch {\n // 进程已经退出\n }\n } catch (error) {\n console.error('终止进程失败:', error);\n }\n\n processes.delete(processKey);\n await saveProcessInfo();\n \n // 清理日志文件(使用日志管理器)\n await deleteProcessLogs(processKey);\n\n return NextResponse.json({\n success: true,\n message: '进程已停止'\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}","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":[5]}
|
|
1
|
+
{"version":3,"sources":["turbopack:///[project]/packages/server/src/lib/workspace-types.ts","turbopack:///[project]/packages/server/src/lib/workspace-config.ts","turbopack:///[project]/packages/server/src/lib/log-manager.ts","turbopack:///[project]/packages/server/src/lib/process-monitor.ts","turbopack:///[project]/packages/server/src/app/api/process/start/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 ApiProxyRewrite {\n mode: 'none' | 'remove' | 'replace';\n targetPrefix?: string;\n}\n\nexport interface ApiProxyItem {\n prefix: string;\n proxyKey?: string;\n currentProxy: string;\n proxyEnv: {\n [key: string]: string;\n };\n rewrite?: ApiProxyRewrite;\n}\n\nexport interface ProjectConfig {\n repo: string;\n mockingIntercept?: boolean;\n mockOpen?: boolean;\n envs: {\n [envName: string]: {\n host: string;\n envFileName: string;\n apiProxies: ApiProxyItem[];\n subApps?: string[];\n startCommand?: 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 projectName?: 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}\n","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 projectName?: string;\n targetDir: string;\n timeout: number;\n onProgress?: (progress: number, message: string) => void;\n onError?: (error: string) => void;\n}\n","/**\n * 日志管理器 - 处理日志文件的轮转、清理和大小限制\n */\nimport fs from 'fs/promises';\nimport path from 'path';\nimport os from 'os';\n\n// 日志配置\nconst LOG_CONFIG = {\n MAX_FILE_SIZE: 5 * 1024 * 1024, // 5MB\n MAX_LOG_FILES: 3, // 保留最多 3 个日志文件\n MAX_LOG_AGE_DAYS: 7, // 日志保留 7 天\n MAX_LINE_LENGTH: 1000, // 单行最大长度\n CLEANUP_INTERVAL: 30 * 60 * 1000, // 30 分钟清理一次\n};\n\n// 获取日志目录\nfunction getLogDir(): string {\n return path.join(os.homedir(), '.prime-process-logs');\n}\n\n// 获取进程日志文件路径\nexport function getProcessLogPath(processKey: string): string {\n return path.join(getLogDir(), `${processKey}.log`);\n}\n\n// 截断过长的日志行\nexport function truncateLogLine(line: string): string {\n if (line.length <= LOG_CONFIG.MAX_LINE_LENGTH) {\n return line;\n }\n return line.substring(0, LOG_CONFIG.MAX_LINE_LENGTH) + '... [truncated]';\n}\n\n/**\n * 获取文件大小\n */\nasync function getFileSize(filePath: string): Promise<number> {\n try {\n const stats = await fs.stat(filePath);\n return stats.size;\n } catch {\n return 0;\n }\n}\n\n/**\n * 轮转日志文件\n * 当日志文件超过大小限制时,将其重命名并创建新文件\n */\nexport async function rotateLogFile(processKey: string): Promise<void> {\n const logPath = getProcessLogPath(processKey);\n const fileSize = await getFileSize(logPath);\n\n // 如果文件大小未超过限制,不需要轮转\n if (fileSize < LOG_CONFIG.MAX_FILE_SIZE) {\n return;\n }\n\n console.log(`[日志管理] 轮转日志文件: ${processKey}, 大小: ${(fileSize / 1024 / 1024).toFixed(2)}MB`);\n\n try {\n // 删除最旧的日志文件\n const oldestLogPath = `${logPath}.${LOG_CONFIG.MAX_LOG_FILES}`;\n try {\n await fs.unlink(oldestLogPath);\n } catch {\n // 文件不存在,忽略\n }\n\n // 轮转现有的日志文件\n for (let i = LOG_CONFIG.MAX_LOG_FILES - 1; i >= 1; i--) {\n const oldPath = i === 1 ? logPath : `${logPath}.${i}`;\n const newPath = `${logPath}.${i + 1}`;\n\n try {\n await fs.rename(oldPath, newPath);\n } catch {\n // 文件不存在,继续\n }\n }\n\n // 重命名当前日志文件\n await fs.rename(logPath, `${logPath}.1`);\n\n // 创建新的空日志文件\n await fs.writeFile(logPath, '', 'utf-8');\n\n console.log(`[日志管理] 日志轮转完成: ${processKey}`);\n } catch (error) {\n console.error(`[日志管理] 轮转日志文件失败: ${processKey}`, error);\n }\n}\n\n/**\n * 追加日志到文件\n * 如果文件过大,先进行轮转\n */\nexport async function appendLog(processKey: string, logLine: string): Promise<void> {\n // 先检查是否需要轮转\n await rotateLogFile(processKey);\n\n const logPath = getProcessLogPath(processKey);\n const truncatedLine = truncateLogLine(logLine);\n\n try {\n // 确保日志目录存在\n await fs.mkdir(getLogDir(), { recursive: true });\n\n // 追加日志\n await fs.appendFile(logPath, truncatedLine + '\\n', 'utf-8');\n } catch (error) {\n console.error(`[日志管理] 追加日志失败: ${processKey}`, error);\n }\n}\n\n/**\n * 批量写入日志(用于初始写入或同步)\n */\nexport async function writeLogsSync(processKey: string, logs: string[]): Promise<void> {\n await rotateLogFile(processKey);\n\n const logPath = getProcessLogPath(processKey);\n const truncatedLogs = logs.map(line => truncateLogLine(line));\n\n try {\n await fs.mkdir(getLogDir(), { recursive: true });\n await fs.writeFile(logPath, truncatedLogs.join('\\n') + '\\n', 'utf-8');\n } catch (error) {\n console.error(`[日志管理] 写入日志失败: ${processKey}`, error);\n }\n}\n\n/**\n * 读取日志文件的最后 N 行\n */\nexport async function readLastNLines(processKey: string, n: number = 100): Promise<string[]> {\n const logPath = getProcessLogPath(processKey);\n\n try {\n const content = await fs.readFile(logPath, 'utf-8');\n const lines = content.split('\\n').filter(line => line.trim());\n return lines.slice(-n);\n } catch {\n return [];\n }\n}\n\n/**\n * 清理旧的日志文件\n * 删除超过保留期限的日志文件\n */\nexport async function cleanupOldLogs(): Promise<void> {\n console.log('[日志管理] 开始清理旧日志...');\n\n try {\n const logDir = getLogDir();\n\n // 确保目录存在\n try {\n await fs.access(logDir);\n } catch {\n console.log('[日志管理] 日志目录不存在,无需清理');\n return;\n }\n\n const files = await fs.readdir(logDir);\n const now = Date.now();\n const maxAge = LOG_CONFIG.MAX_LOG_AGE_DAYS * 24 * 60 * 60 * 1000;\n\n let deletedCount = 0;\n let freedSpace = 0;\n\n for (const file of files) {\n const filePath = path.join(logDir, file);\n\n try {\n const stats = await fs.stat(filePath);\n\n // 删除超过保留期的文件\n if (now - stats.mtime.getTime() > maxAge) {\n freedSpace += stats.size;\n try {\n await fs.unlink(filePath);\n deletedCount++;\n console.log(`[日志管理] 删除过期日志: ${file}`);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (unlinkError: any) {\n // 如果文件已经不存在,忽略错误\n if (unlinkError?.code !== 'ENOENT') {\n console.error(`[日志管理] 删除文件失败: ${file}`, unlinkError);\n }\n }\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (error: any) {\n // 如果文件不存在,跳过(可能已被删除)\n if (error?.code !== 'ENOENT') {\n console.error(`[日志管理] 处理文件失败: ${file}`, error);\n }\n }\n }\n\n console.log(`[日志管理] 清理完成: 删除 ${deletedCount} 个文件, 释放 ${(freedSpace / 1024 / 1024).toFixed(2)}MB`);\n } catch (error) {\n console.error('[日志管理] 清理日志失败:', error);\n }\n}\n\n/**\n * 删除指定进程的所有日志文件\n */\nexport async function deleteProcessLogs(processKey: string): Promise<void> {\n const logPath = getProcessLogPath(processKey);\n\n try {\n // 删除主日志文件\n await fs.unlink(logPath);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (error: any) {\n // 文件不存在,忽略\n if (error?.code !== 'ENOENT') {\n console.error(`[日志管理] 删除主日志文件失败: ${processKey}`, error);\n }\n }\n\n // 删除轮转的日志文件\n for (let i = 1; i <= LOG_CONFIG.MAX_LOG_FILES; i++) {\n try {\n await fs.unlink(`${logPath}.${i}`);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (error: any) {\n // 文件不存在,忽略\n if (error?.code !== 'ENOENT') {\n console.error(`[日志管理] 删除轮转日志文件失败: ${processKey}.${i}`, error);\n }\n }\n }\n\n console.log(`[日志管理] 删除进程日志: ${processKey}`);\n}\n\n/**\n * 获取日志目录的总大小\n */\nexport async function getLogsDirSize(): Promise<{ totalSize: number; fileCount: number }> {\n try {\n const logDir = getLogDir();\n const files = await fs.readdir(logDir);\n\n let totalSize = 0;\n let fileCount = 0;\n\n for (const file of files) {\n try {\n const stats = await fs.stat(path.join(logDir, file));\n totalSize += stats.size;\n fileCount++;\n } catch {\n // 忽略错误\n }\n }\n\n return { totalSize, fileCount };\n } catch {\n return { totalSize: 0, fileCount: 0 };\n }\n}\n\n// 定期清理任务\nlet cleanupTimer: NodeJS.Timeout | null = null;\n\n/**\n * 启动定期清理任务\n */\nexport function startLogCleanupTask(): void {\n if (cleanupTimer) {\n return; // 已经启动\n }\n\n console.log('[日志管理] 启动定期清理任务');\n\n // 立即执行一次\n cleanupOldLogs();\n\n // 设置定期清理\n cleanupTimer = setInterval(() => {\n cleanupOldLogs();\n }, LOG_CONFIG.CLEANUP_INTERVAL);\n}\n\n/**\n * 停止定期清理任务\n */\nexport function stopLogCleanupTask(): void {\n if (cleanupTimer) {\n clearInterval(cleanupTimer);\n cleanupTimer = null;\n console.log('[日志管理] 停止定期清理任务');\n }\n}\n\n// 进程退出时停止清理任务\nprocess.on('SIGINT', () => {\n stopLogCleanupTask();\n});\n\nprocess.on('SIGTERM', () => {\n stopLogCleanupTask();\n});\n\n","import fs from 'fs/promises';\nimport path from 'path';\nimport os from 'os';\nimport { exec } from 'child_process';\nimport { promisify } from 'util';\n\nconst execAsync = promisify(exec);\n\n// 进程信息接口\ninterface ProcessInfo {\n key: string;\n projectName: string;\n envName: string;\n pid: number;\n startTime: Date;\n port: string;\n}\n\n// 获取进程存储文件路径\nfunction getProcessStorePath() {\n return path.join(os.homedir(), '.prime-processes.json');\n}\n\n// 检查进程是否仍在运行\nasync function isProcessRunning(pid: number): Promise<boolean> {\n try {\n if (process.platform !== 'win32') {\n process.kill(pid, 0);\n return true;\n } else {\n const { stdout } = await execAsync(`tasklist /FI \"PID eq ${pid}\"`);\n return stdout.includes(pid.toString());\n }\n } catch {\n return false;\n }\n}\n\n// 加载并清理过期的进程信息\nexport async function loadAndCleanProcesses(): Promise<ProcessInfo[]> {\n try {\n const processInfoContent = await fs.readFile(getProcessStorePath(), 'utf-8');\n const processInfoList: ProcessInfo[] = JSON.parse(processInfoContent);\n \n // 过滤出仍在运行的进程\n const runningProcesses: ProcessInfo[] = [];\n \n for (const processInfo of processInfoList) {\n const isRunning = await isProcessRunning(processInfo.pid);\n if (isRunning) {\n runningProcesses.push(processInfo);\n }\n }\n \n // 如果有进程被清理,更新文件\n if (runningProcesses.length !== processInfoList.length) {\n await fs.writeFile(getProcessStorePath(), JSON.stringify(runningProcesses, null, 2));\n }\n \n return runningProcesses;\n } catch {\n // 文件不存在或解析错误,返回空数组\n return [];\n }\n}\n\n// 初始化进程监控 - 在应用启动时调用\nexport async function initializeProcessMonitoring() {\n console.log('初始化进程监控...');\n const processes = await loadAndCleanProcesses();\n console.log(`发现 ${processes.length} 个正在运行的进程`);\n return processes;\n}","import { NextRequest, NextResponse } from 'next/server';\nimport { spawn } from 'child_process';\nimport path from 'path';\nimport fs from 'fs/promises';\nimport os from 'os';\nimport { loadAndCleanProcesses } from '@/lib/process-monitor';\nimport { getProjectsConfig } from '@/lib/workspace-config';\nimport { WORKSPACE_CONFIG } from '@/lib/workspace-types';\nimport { \n appendLog, \n readLastNLines, \n deleteProcessLogs,\n startLogCleanupTask,\n truncateLogLine \n} from '@/lib/log-manager';\n\n// 存储进程信息的Map\ninterface ProcessData {\n process: {\n pid: number;\n killed: boolean;\n kill?: () => void;\n on?: (event: string, callback: (code?: number) => void) => void;\n };\n projectName: string;\n envName: string;\n startTime: Date;\n port: string;\n recentLogs: string[]; // 只保留最近的少量日志在内存中\n}\n\nconst processes = new Map<string, ProcessData>();\nconst MAX_MEMORY_LOG_LINES = 50; // 内存中只保留最近 50 行\n\n// 获取进程存储文件路径\nfunction getProcessStorePath() {\n return path.join(os.homedir(), '.prime-processes.json');\n}\n\n// 追加日志到文件和内存\nasync function logToFileAndMemory(processKey: string, logLine: string, processData: ProcessData) {\n // 截断过长的日志行\n const truncated = truncateLogLine(logLine);\n \n // 追加到文件(使用日志管理器,自动处理轮转)\n await appendLog(processKey, truncated);\n \n // 只在内存中保留最近的几条\n processData.recentLogs.push(truncated);\n if (processData.recentLogs.length > MAX_MEMORY_LOG_LINES) {\n processData.recentLogs.shift();\n }\n}\n\n// 保存进程信息到文件\nasync function saveProcessInfo() {\n const processInfo: {\n key: string;\n projectName: string;\n envName: string;\n startTime: Date;\n port: string;\n pid: number;\n }[] = [];\n processes.forEach((value, key) => {\n processInfo.push({\n key,\n projectName: value.projectName,\n envName: value.envName,\n startTime: value.startTime,\n port: value.port,\n pid: value.process.pid\n });\n });\n \n try {\n await fs.writeFile(getProcessStorePath(), JSON.stringify(processInfo, null, 2));\n } catch (error) {\n console.error('保存进程信息失败:', error);\n }\n}\n\n// 在启动时加载现有进程信息\nlet processesInitialized = false;\nasync function ensureProcessesLoaded() {\n if (!processesInitialized) {\n // 启动日志清理任务\n startLogCleanupTask();\n \n const existingProcesses = await loadAndCleanProcesses();\n for (const processInfo of existingProcesses) {\n // 恢复进程信息到内存,但不恢复实际的进程对象\n // 因为我们只需要知道进程存在,状态查询会检查实际的PID\n // 只加载最近的日志到内存\n const recentLogs = await readLastNLines(processInfo.key, MAX_MEMORY_LOG_LINES);\n \n processes.set(processInfo.key, {\n process: { pid: processInfo.pid, killed: false },\n projectName: processInfo.projectName,\n envName: processInfo.envName,\n startTime: new Date(processInfo.startTime),\n port: processInfo.port,\n recentLogs\n });\n }\n processesInitialized = true;\n }\n}\n\nexport async function POST(request: NextRequest) {\n await ensureProcessesLoaded();\n try {\n const { projectName, envName, startCommand } = await request.json();\n\n if (!projectName || !envName || !startCommand) {\n return NextResponse.json({\n success: false,\n error: '缺少必要参数'\n }, { status: 400 });\n }\n\n // 生成进程的唯一标识\n const processKey = `${projectName}-${envName}`;\n\n // 检查进程是否已经在运行\n if (processes.has(processKey)) {\n const existingProcess = processes.get(processKey);\n if (existingProcess && existingProcess.process && !existingProcess.process.killed) {\n return NextResponse.json({\n success: false,\n error: '该环境已经在运行中'\n }, { status: 400 });\n }\n }\n\n // 读取配置文件获取工作区路径\n const config = await getProjectsConfig();\n \n // 使用工作区常量路径\n const workspacePath = WORKSPACE_CONFIG.WORKSPACE_ROOT;\n \n // 构建项目路径\n const projectPath = path.join(workspacePath, projectName);\n\n // 检查项目目录是否存在\n try {\n await fs.access(projectPath);\n } catch {\n return NextResponse.json({\n success: false,\n error: '项目目录不存在'\n }, { status: 404 });\n }\n\n // 解析命令\n const [command, ...args] = startCommand.split(' ');\n\n // 启动进程 - 不传递 env 参数,让子进程继承父进程环境变量\n // 但通过环境变量覆盖确保开发模式\n const childProcess = spawn(command, args, {\n cwd: projectPath,\n shell: true,\n detached: false,\n stdio: ['ignore', 'pipe', 'pipe'],\n env: {\n ...process.env,\n NODE_ENV: 'development', // 强制设置为开发模式\n FORCE_COLOR: '1', // 保留颜色输出\n }\n });\n\n // 获取项目配置中的端口信息\n const projectConfig = config[projectName];\n const envConfig = projectConfig?.envs?.[envName];\n const port = envConfig?.host?.split(':').pop() || '';\n \n // 存储进程信息\n const processData: ProcessData = {\n process: {\n pid: childProcess.pid || 0,\n killed: false,\n kill: () => childProcess.kill(),\n on: (event: string, callback: (code?: number) => void) => {\n childProcess.on(event, callback);\n }\n },\n projectName,\n envName,\n startTime: new Date(),\n port,\n recentLogs: [] // 只在内存中保留最近的日志\n };\n \n processes.set(processKey, processData);\n \n // 捕获标准输出\n if (childProcess.stdout) {\n childProcess.stdout.on('data', async (data: Buffer) => {\n const text = data.toString();\n const lines = text.split('\\n');\n \n for (const line of lines) {\n // 过滤掉只包含控制序列的行\n const cleanedLine = line\n .replace(/\\x1b\\[[0-9;]*m/g, '') // 移除颜色代码\n .replace(/\\x1b\\[[0-9]*[A-Z]/g, '') // 移除光标控制\n .replace(/\\[\\d+[A-Z]/g, '') // 移除其他控制序列\n .trim();\n \n // 如果清理后的行不为空,则记录\n if (cleanedLine) {\n const logEntry = `[${new Date().toISOString()}] [STDOUT] ${line}`;\n await logToFileAndMemory(processKey, logEntry, processData);\n }\n }\n });\n }\n \n // 捕获标准错误\n if (childProcess.stderr) {\n childProcess.stderr.on('data', async (data: Buffer) => {\n const text = data.toString();\n const lines = text.split('\\n');\n \n for (const line of lines) {\n // 过滤掉只包含控制序列的行\n const cleanedLine = line\n .replace(/\\x1b\\[[0-9;]*m/g, '')\n .replace(/\\x1b\\[[0-9]*[A-Z]/g, '')\n .replace(/\\[\\d+[A-Z]/g, '')\n .trim();\n \n if (cleanedLine) {\n const logEntry = `[${new Date().toISOString()}] [STDERR] ${line}`;\n await logToFileAndMemory(processKey, logEntry, processData);\n }\n }\n });\n }\n\n // 保存进程信息到文件\n await saveProcessInfo();\n \n // 监听进程退出\n childProcess.on('exit', async (code) => {\n console.log(`进程 ${processKey} 退出,退出码: ${code}`);\n const logEntry = `[${new Date().toISOString()}] [SYSTEM] 进程退出,退出码: ${code}`;\n await appendLog(processKey, logEntry);\n \n processes.delete(processKey);\n await saveProcessInfo();\n });\n\n childProcess.on('error', (error) => {\n console.error(`进程 ${processKey} 错误:`, error);\n processes.delete(processKey);\n saveProcessInfo();\n });\n\n // 等待一小段时间确保进程启动\n await new Promise(resolve => setTimeout(resolve, 2000));\n\n // 检查进程是否仍在运行\n if (childProcess.killed) {\n processes.delete(processKey);\n await saveProcessInfo();\n return NextResponse.json({\n success: false,\n error: '进程启动失败'\n }, { status: 500 });\n }\n\n return NextResponse.json({\n success: true,\n data: {\n pid: childProcess.pid,\n startTime: new Date(),\n port\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// 停止进程\nexport async function DELETE(request: NextRequest) {\n await ensureProcessesLoaded();\n try {\n const { searchParams } = new URL(request.url);\n const projectName = searchParams.get('projectName');\n const envName = searchParams.get('envName');\n\n if (!projectName || !envName) {\n return NextResponse.json({\n success: false,\n error: '缺少必要参数'\n }, { status: 400 });\n }\n\n const processKey = `${projectName}-${envName}`;\n const processInfo = processes.get(processKey);\n\n if (!processInfo) {\n return NextResponse.json({\n success: false,\n error: '进程未找到'\n }, { status: 404 });\n }\n\n try {\n // 尝试优雅地终止进程\n process.kill(processInfo.process.pid, 'SIGTERM');\n \n // 给进程一些时间来清理\n await new Promise(resolve => setTimeout(resolve, 1000));\n \n // 如果进程仍在运行,强制终止\n try {\n process.kill(processInfo.process.pid, 0); // 检查进程是否存在\n process.kill(processInfo.process.pid, 'SIGKILL');\n } catch {\n // 进程已经退出\n }\n } catch (error) {\n console.error('终止进程失败:', error);\n }\n\n processes.delete(processKey);\n await saveProcessInfo();\n \n // 清理日志文件(使用日志管理器)\n await deleteProcessLogs(processKey);\n\n return NextResponse.json({\n success: true,\n message: '进程已停止'\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}","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":[5]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["turbopack:///[project]/packages/server/src/lib/workspace-types.ts","turbopack:///[project]/packages/server/src/app/api/workspace/create/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 projectName?: 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}\n","import { NextRequest } from 'next/server';\nimport { writeFile, access, mkdir } from 'fs/promises';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport { exec } from 'child_process';\nimport { promisify } from 'util';\nimport { WORKSPACE_CONFIG } from '@/lib/workspace-types';\nimport type { EditorType } from '@/lib/editor-operations';\n\nconst execAsync = promisify(exec);\n\ninterface WorkspaceFolder {\n path: string;\n}\n\ninterface WorkspaceConfig {\n folders: WorkspaceFolder[];\n settings: Record<string, unknown>;\n}\n\n// 工作区文件存储目录\nconst WORKSPACE_FILES_DIR = join(homedir(), '.prime-workspaces');\n\n// 编辑器命令映射\nconst EDITOR_COMMANDS: Record<EditorType, string> = {\n cursor: 'cursor',\n vscode: 'code',\n webstorm: 'webstorm',\n};\n\n// 编辑器显示名称映射\nconst EDITOR_NAMES: Record<EditorType, string> = {\n cursor: 'Cursor',\n vscode: 'VSCode',\n webstorm: 'WebStorm',\n};\n\n/**\n * 创建并打开工作区(支持 Cursor、VSCode、WebStorm)\n */\nexport async function POST(request: NextRequest) {\n try {\n const { projects, editor = 'cursor' } = await request.json() as { projects: string[]; editor?: EditorType };\n\n if (!projects || !Array.isArray(projects) || projects.length === 0) {\n return Response.json(\n { success: false, error: '请至少选择一个项目' },\n { status: 400 }\n );\n }\n\n const workspacePath = WORKSPACE_CONFIG.WORKSPACE_ROOT;\n\n // 对项目名称排序,生成稳定的文件名\n const sortedProjects = [...projects].sort();\n const workspaceFileName = `${sortedProjects.join('-')}.code-workspace`;\n \n // 确保工作区文件目录存在\n try {\n await access(WORKSPACE_FILES_DIR);\n } catch {\n await mkdir(WORKSPACE_FILES_DIR, { recursive: true });\n }\n\n const workspaceFilePath = join(WORKSPACE_FILES_DIR, workspaceFileName);\n\n // 检查工作区文件是否已存在\n let fileExists = false;\n try {\n await access(workspaceFilePath);\n fileExists = true;\n } catch {\n // 文件不存在,需要创建\n fileExists = false;\n }\n\n // 如果文件不存在,创建新的工作区文件\n if (!fileExists) {\n // 构建工作区配置\n const workspaceConfig: WorkspaceConfig = {\n folders: sortedProjects.map((projectName: string) => ({\n path: join(workspacePath, projectName)\n })),\n settings: {}\n };\n\n // 写入工作区文件\n await writeFile(\n workspaceFilePath,\n JSON.stringify(workspaceConfig, null, 2),\n 'utf-8'\n );\n }\n\n // 使用对应编辑器命令打开工作区\n try {\n // 创建一个干净的环境变量,避免继承当前进程的 NODE_ENV 等环境变量\n const cleanEnv = Object.fromEntries(\n Object.entries(process.env).filter(([key]) => key !== 'NODE_ENV')\n );\n\n const editorCommand = EDITOR_COMMANDS[editor] || EDITOR_COMMANDS.cursor;\n const editorName = EDITOR_NAMES[editor] || EDITOR_NAMES.cursor;\n\n await execAsync(`${editorCommand} \"${workspaceFilePath}\"`, {\n env: cleanEnv as NodeJS.ProcessEnv\n });\n\n return Response.json({\n success: true,\n message: fileExists ? `已在 ${editorName} 中打开现有工作区` : `工作区已创建并在 ${editorName} 中打开`,\n workspaceFile: workspaceFilePath,\n isExisting: fileExists,\n editor: editorName\n });\n } catch (execError) {\n const errorMessage = execError instanceof Error ? execError.message : String(execError);\n const editorName = EDITOR_NAMES[editor] || EDITOR_NAMES.cursor;\n return Response.json(\n { success: false, error: `无法打开 ${editorName}: ${errorMessage}` },\n { status: 500 }\n );\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.error('创建工作区失败:', error);\n \n return Response.json(\n { success: false, error: `创建工作区失败: ${errorMessage}` },\n { status: 500 }\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]}
|
|
1
|
+
{"version":3,"sources":["turbopack:///[project]/packages/server/src/lib/workspace-types.ts","turbopack:///[project]/packages/server/src/app/api/workspace/create/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 ApiProxyRewrite {\n mode: 'none' | 'remove' | 'replace';\n targetPrefix?: string;\n}\n\nexport interface ApiProxyItem {\n prefix: string;\n proxyKey?: string;\n currentProxy: string;\n proxyEnv: {\n [key: string]: string;\n };\n rewrite?: ApiProxyRewrite;\n}\n\nexport interface ProjectConfig {\n repo: string;\n mockingIntercept?: boolean;\n mockOpen?: boolean;\n envs: {\n [envName: string]: {\n host: string;\n envFileName: string;\n apiProxies: ApiProxyItem[];\n subApps?: string[];\n startCommand?: 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 projectName?: 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}\n","import { NextRequest } from 'next/server';\nimport { writeFile, access, mkdir } from 'fs/promises';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport { exec } from 'child_process';\nimport { promisify } from 'util';\nimport { WORKSPACE_CONFIG } from '@/lib/workspace-types';\nimport type { EditorType } from '@/lib/editor-operations';\n\nconst execAsync = promisify(exec);\n\ninterface WorkspaceFolder {\n path: string;\n}\n\ninterface WorkspaceConfig {\n folders: WorkspaceFolder[];\n settings: Record<string, unknown>;\n}\n\n// 工作区文件存储目录\nconst WORKSPACE_FILES_DIR = join(homedir(), '.prime-workspaces');\n\n// 编辑器命令映射\nconst EDITOR_COMMANDS: Record<EditorType, string> = {\n cursor: 'cursor',\n vscode: 'code',\n webstorm: 'webstorm',\n};\n\n// 编辑器显示名称映射\nconst EDITOR_NAMES: Record<EditorType, string> = {\n cursor: 'Cursor',\n vscode: 'VSCode',\n webstorm: 'WebStorm',\n};\n\n/**\n * 创建并打开工作区(支持 Cursor、VSCode、WebStorm)\n */\nexport async function POST(request: NextRequest) {\n try {\n const { projects, editor = 'cursor' } = await request.json() as { projects: string[]; editor?: EditorType };\n\n if (!projects || !Array.isArray(projects) || projects.length === 0) {\n return Response.json(\n { success: false, error: '请至少选择一个项目' },\n { status: 400 }\n );\n }\n\n const workspacePath = WORKSPACE_CONFIG.WORKSPACE_ROOT;\n\n // 对项目名称排序,生成稳定的文件名\n const sortedProjects = [...projects].sort();\n const workspaceFileName = `${sortedProjects.join('-')}.code-workspace`;\n \n // 确保工作区文件目录存在\n try {\n await access(WORKSPACE_FILES_DIR);\n } catch {\n await mkdir(WORKSPACE_FILES_DIR, { recursive: true });\n }\n\n const workspaceFilePath = join(WORKSPACE_FILES_DIR, workspaceFileName);\n\n // 检查工作区文件是否已存在\n let fileExists = false;\n try {\n await access(workspaceFilePath);\n fileExists = true;\n } catch {\n // 文件不存在,需要创建\n fileExists = false;\n }\n\n // 如果文件不存在,创建新的工作区文件\n if (!fileExists) {\n // 构建工作区配置\n const workspaceConfig: WorkspaceConfig = {\n folders: sortedProjects.map((projectName: string) => ({\n path: join(workspacePath, projectName)\n })),\n settings: {}\n };\n\n // 写入工作区文件\n await writeFile(\n workspaceFilePath,\n JSON.stringify(workspaceConfig, null, 2),\n 'utf-8'\n );\n }\n\n // 使用对应编辑器命令打开工作区\n try {\n // 创建一个干净的环境变量,避免继承当前进程的 NODE_ENV 等环境变量\n const cleanEnv = Object.fromEntries(\n Object.entries(process.env).filter(([key]) => key !== 'NODE_ENV')\n );\n\n const editorCommand = EDITOR_COMMANDS[editor] || EDITOR_COMMANDS.cursor;\n const editorName = EDITOR_NAMES[editor] || EDITOR_NAMES.cursor;\n\n await execAsync(`${editorCommand} \"${workspaceFilePath}\"`, {\n env: cleanEnv as NodeJS.ProcessEnv\n });\n\n return Response.json({\n success: true,\n message: fileExists ? `已在 ${editorName} 中打开现有工作区` : `工作区已创建并在 ${editorName} 中打开`,\n workspaceFile: workspaceFilePath,\n isExisting: fileExists,\n editor: editorName\n });\n } catch (execError) {\n const errorMessage = execError instanceof Error ? execError.message : String(execError);\n const editorName = EDITOR_NAMES[editor] || EDITOR_NAMES.cursor;\n return Response.json(\n { success: false, error: `无法打开 ${editorName}: ${errorMessage}` },\n { status: 500 }\n );\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.error('创建工作区失败:', error);\n \n return Response.json(\n { success: false, error: `创建工作区失败: ${errorMessage}` },\n { status: 500 }\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]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["turbopack:///[project]/packages/server/src/lib/workspace-types.ts","turbopack:///[project]/packages/server/src/lib/workspace-config.ts","turbopack:///[project]/packages/server/src/app/api/get-mock-data/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 projectName?: 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}\n","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 projectName?: string;\n targetDir: string;\n timeout: number;\n onProgress?: (progress: number, message: string) => void;\n onError?: (error: string) => void;\n}\n","import { NextRequest, NextResponse } from 'next/server';\nimport { promises as fs } from 'fs';\nimport { join, resolve } from 'path';\nimport { getProjectsConfig } from '@/lib/workspace-config';\nimport { WORKSPACE_CONFIG } from '@/lib/workspace-types';\nimport { createRequire } from \"module\";\nconst require = createRequire(import.meta.url);\n\n// 预先加载mockjs并注入到全局,确保外部mock文件可以正常require\ntry {\n const mockjs = require('mockjs');\n // 将mockjs注入到全局require缓存中,使用绝对路径\n const Module = require('module');\n const originalRequire = Module.prototype.require;\n \n Module.prototype.require = function(id: string, ...args: unknown[]) {\n if (id === 'mockjs') {\n return mockjs;\n }\n return originalRequire.apply(this, [id, ...args]);\n };\n} catch (error) {\n console.warn('mockjs模块加载失败,可能影响mock文件功能:', error);\n}\n\nexport async function GET(request: NextRequest) {\n try {\n const { searchParams } = new URL(request.url);\n const projectName = searchParams.get('project');\n const url = searchParams.get('url');\n const method = searchParams.get('method');\n\n if (!projectName || !url || !method) {\n return NextResponse.json(\n { success: false, error: '缺少必要参数:project, url, method' },\n { status: 400 },\n );\n }\n\n // 验证项目是否存在\n const projectsConfig = await getProjectsConfig();\n if (!projectsConfig[projectName]) {\n return NextResponse.json(\n { success: false, error: `项目 ${projectName} 不存在` },\n { status: 404 },\n );\n }\n\n // 检查项目是否开启Mock功能\n const projectConfig = projectsConfig[projectName];\n if (!projectConfig.mockOpen) {\n return NextResponse.json(\n { success: false, error: 'Mock功能未开启' },\n { status: 400 },\n );\n }\n\n\n // 处理URL路径:移除查询参数,转换/为_\n const cleanUrl = url.split('?')[0];\n const apiName = cleanUrl.replace(/^\\//, '').replace(/\\//g, '_') || 'root';\n\n // 构建Mock文件路径\n const projectPath = join(WORKSPACE_CONFIG.WORKSPACE_ROOT, projectName);\n const mockPath = join(projectPath, '.mock');\n const apiPath = join(mockPath, apiName);\n const methodPath = join(apiPath, method.toLowerCase());\n const settingFilePath = join(methodPath, 'setting.cjs');\n\n // 检查setting.cjs文件是否存在\n try {\n await fs.access(settingFilePath);\n } catch {\n return NextResponse.json(\n { success: false, error: `Mock配置文件不存在: ${apiName}/${method.toLowerCase()}/setting.cjs` },\n { status: 404 },\n );\n }\n\n // 读取setting.cjs文件内容\n let currentSite: string | undefined;\n let openSites: string[] = [];\n try {\n const setting = require(resolve(settingFilePath));\n delete require.cache[resolve(settingFilePath)];\n if (setting) {\n try {\n // 使用Function构造器替代eval,更安全\n currentSite = setting.currentSite;\n openSites = Array.isArray(setting.open) ? setting.open : [];\n } catch (parseError) {\n console.warn(`解析setting.cjs失败: ${settingFilePath}`, parseError);\n }\n }\n } catch (error) {\n console.error(`读取setting.cjs失败: ${settingFilePath}`, error);\n return NextResponse.json(\n { success: false, error: '读取Mock配置失败' },\n { status: 500 },\n );\n }\n\n if (!currentSite) {\n return NextResponse.json(\n { success: false, error: '未找到当前选中的Mock场景' },\n { status: 404 },\n );\n }\n\n // 检查当前场景是否在开启的Mock场景列表中\n if (!openSites.includes(currentSite)) {\n return NextResponse.json(\n { success: false, error: `当前场景 \"${currentSite}\" 未开启Mock功能` },\n { status: 400 },\n );\n }\n\n // 构建Mock场景文件路径\n const mockFilePath = join(methodPath, `${currentSite}.cjs`);\n\n // 检查Mock场景文件是否存在\n try {\n await fs.access(mockFilePath);\n } catch {\n return NextResponse.json(\n { success: false, error: `Mock场景文件不存在: ${apiName}/${method.toLowerCase()}/${currentSite}.cjs` },\n { status: 404 },\n );\n }\n\n // 读取Mock场景文件内容\n let mockData: unknown;\n try {\n const mockContent = require(resolve(mockFilePath));\n delete require.cache[resolve(mockFilePath)];\n // 使用更安全的方式解析module.exports\n if (mockContent) {\n try {\n // 使用Function构造器替代eval,更安全\n mockData = mockContent;\n } catch (parseError) {\n console.warn(`解析Mock文件失败: ${mockFilePath}`, parseError);\n return NextResponse.json(\n { success: false, error: '解析Mock数据失败' },\n { status: 500 },\n );\n }\n } else {\n return NextResponse.json(\n { success: false, error: 'Mock文件格式不正确' },\n { status: 500 },\n );\n }\n } catch (error) {\n console.error(`读取Mock文件失败: ${mockFilePath}`, error);\n return NextResponse.json(\n { success: false, error: '读取Mock数据失败' },\n { status: 500 },\n );\n }\n\n return NextResponse.json({\n success: true,\n data: {\n projectName,\n apiName,\n method: method.toLowerCase(),\n currentSite,\n mockData,\n filePath: join('.mock', apiName, method.toLowerCase(), `${currentSite}.cjs`),\n },\n message: 'Mock数据获取成功',\n });\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : '获取Mock数据失败';\n console.error('获取Mock数据失败:', 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":[3]}
|
|
1
|
+
{"version":3,"sources":["turbopack:///[project]/packages/server/src/lib/workspace-types.ts","turbopack:///[project]/packages/server/src/lib/workspace-config.ts","turbopack:///[project]/packages/server/src/app/api/get-mock-data/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 ApiProxyRewrite {\n mode: 'none' | 'remove' | 'replace';\n targetPrefix?: string;\n}\n\nexport interface ApiProxyItem {\n prefix: string;\n proxyKey?: string;\n currentProxy: string;\n proxyEnv: {\n [key: string]: string;\n };\n rewrite?: ApiProxyRewrite;\n}\n\nexport interface ProjectConfig {\n repo: string;\n mockingIntercept?: boolean;\n mockOpen?: boolean;\n envs: {\n [envName: string]: {\n host: string;\n envFileName: string;\n apiProxies: ApiProxyItem[];\n subApps?: string[];\n startCommand?: 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 projectName?: 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}\n","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 projectName?: string;\n targetDir: string;\n timeout: number;\n onProgress?: (progress: number, message: string) => void;\n onError?: (error: string) => void;\n}\n","import { NextRequest, NextResponse } from 'next/server';\nimport { promises as fs } from 'fs';\nimport { join, resolve } from 'path';\nimport { getProjectsConfig } from '@/lib/workspace-config';\nimport { WORKSPACE_CONFIG } from '@/lib/workspace-types';\nimport { createRequire } from \"module\";\nconst require = createRequire(import.meta.url);\n\n// 预先加载mockjs并注入到全局,确保外部mock文件可以正常require\ntry {\n const mockjs = require('mockjs');\n // 将mockjs注入到全局require缓存中,使用绝对路径\n const Module = require('module');\n const originalRequire = Module.prototype.require;\n \n Module.prototype.require = function(id: string, ...args: unknown[]) {\n if (id === 'mockjs') {\n return mockjs;\n }\n return originalRequire.apply(this, [id, ...args]);\n };\n} catch (error) {\n console.warn('mockjs模块加载失败,可能影响mock文件功能:', error);\n}\n\nexport async function GET(request: NextRequest) {\n try {\n const { searchParams } = new URL(request.url);\n const projectName = searchParams.get('project');\n const url = searchParams.get('url');\n const method = searchParams.get('method');\n\n if (!projectName || !url || !method) {\n return NextResponse.json(\n { success: false, error: '缺少必要参数:project, url, method' },\n { status: 400 },\n );\n }\n\n // 验证项目是否存在\n const projectsConfig = await getProjectsConfig();\n if (!projectsConfig[projectName]) {\n return NextResponse.json(\n { success: false, error: `项目 ${projectName} 不存在` },\n { status: 404 },\n );\n }\n\n // 检查项目是否开启Mock功能\n const projectConfig = projectsConfig[projectName];\n if (!projectConfig.mockOpen) {\n return NextResponse.json(\n { success: false, error: 'Mock功能未开启' },\n { status: 400 },\n );\n }\n\n\n // 处理URL路径:移除查询参数,转换/为_\n const cleanUrl = url.split('?')[0];\n const apiName = cleanUrl.replace(/^\\//, '').replace(/\\//g, '_') || 'root';\n\n // 构建Mock文件路径\n const projectPath = join(WORKSPACE_CONFIG.WORKSPACE_ROOT, projectName);\n const mockPath = join(projectPath, '.mock');\n const apiPath = join(mockPath, apiName);\n const methodPath = join(apiPath, method.toLowerCase());\n const settingFilePath = join(methodPath, 'setting.cjs');\n\n // 检查setting.cjs文件是否存在\n try {\n await fs.access(settingFilePath);\n } catch {\n return NextResponse.json(\n { success: false, error: `Mock配置文件不存在: ${apiName}/${method.toLowerCase()}/setting.cjs` },\n { status: 404 },\n );\n }\n\n // 读取setting.cjs文件内容\n let currentSite: string | undefined;\n let openSites: string[] = [];\n try {\n const setting = require(resolve(settingFilePath));\n delete require.cache[resolve(settingFilePath)];\n if (setting) {\n try {\n // 使用Function构造器替代eval,更安全\n currentSite = setting.currentSite;\n openSites = Array.isArray(setting.open) ? setting.open : [];\n } catch (parseError) {\n console.warn(`解析setting.cjs失败: ${settingFilePath}`, parseError);\n }\n }\n } catch (error) {\n console.error(`读取setting.cjs失败: ${settingFilePath}`, error);\n return NextResponse.json(\n { success: false, error: '读取Mock配置失败' },\n { status: 500 },\n );\n }\n\n if (!currentSite) {\n return NextResponse.json(\n { success: false, error: '未找到当前选中的Mock场景' },\n { status: 404 },\n );\n }\n\n // 检查当前场景是否在开启的Mock场景列表中\n if (!openSites.includes(currentSite)) {\n return NextResponse.json(\n { success: false, error: `当前场景 \"${currentSite}\" 未开启Mock功能` },\n { status: 400 },\n );\n }\n\n // 构建Mock场景文件路径\n const mockFilePath = join(methodPath, `${currentSite}.cjs`);\n\n // 检查Mock场景文件是否存在\n try {\n await fs.access(mockFilePath);\n } catch {\n return NextResponse.json(\n { success: false, error: `Mock场景文件不存在: ${apiName}/${method.toLowerCase()}/${currentSite}.cjs` },\n { status: 404 },\n );\n }\n\n // 读取Mock场景文件内容\n let mockData: unknown;\n try {\n const mockContent = require(resolve(mockFilePath));\n delete require.cache[resolve(mockFilePath)];\n // 使用更安全的方式解析module.exports\n if (mockContent) {\n try {\n // 使用Function构造器替代eval,更安全\n mockData = mockContent;\n } catch (parseError) {\n console.warn(`解析Mock文件失败: ${mockFilePath}`, parseError);\n return NextResponse.json(\n { success: false, error: '解析Mock数据失败' },\n { status: 500 },\n );\n }\n } else {\n return NextResponse.json(\n { success: false, error: 'Mock文件格式不正确' },\n { status: 500 },\n );\n }\n } catch (error) {\n console.error(`读取Mock文件失败: ${mockFilePath}`, error);\n return NextResponse.json(\n { success: false, error: '读取Mock数据失败' },\n { status: 500 },\n );\n }\n\n return NextResponse.json({\n success: true,\n data: {\n projectName,\n apiName,\n method: method.toLowerCase(),\n currentSite,\n mockData,\n filePath: join('.mock', apiName, method.toLowerCase(), `${currentSite}.cjs`),\n },\n message: 'Mock数据获取成功',\n });\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : '获取Mock数据失败';\n console.error('获取Mock数据失败:', 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":[3]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["turbopack:///[project]/packages/server/src/lib/workspace-types.ts","turbopack:///[project]/packages/server/src/app/api/cleanup-project/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
|
|
1
|
+
{"version":3,"sources":["turbopack:///[project]/packages/server/src/lib/workspace-types.ts","turbopack:///[project]/packages/server/src/app/api/cleanup-project/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 ApiProxyRewrite {\n mode: 'none' | 'remove' | 'replace';\n targetPrefix?: string;\n}\n\nexport interface ApiProxyItem {\n prefix: string;\n proxyKey?: string;\n currentProxy: string;\n proxyEnv: {\n [key: string]: string;\n };\n rewrite?: ApiProxyRewrite;\n}\n\nexport interface ProjectConfig {\n repo: string;\n mockingIntercept?: boolean;\n mockOpen?: boolean;\n envs: {\n [envName: string]: {\n host: string;\n envFileName: string;\n apiProxies: ApiProxyItem[];\n subApps?: string[];\n startCommand?: 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 projectName?: 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}\n","import { NextRequest, NextResponse } from 'next/server';\nimport { promises as fs } from 'fs';\nimport { join } from 'path';\nimport { WORKSPACE_CONFIG } from '@/lib/workspace-types';\n\nexport async function POST(request: NextRequest) {\n try {\n const { projectName } = await request.json();\n\n if (!projectName || typeof projectName !== 'string') {\n return NextResponse.json({\n success: false,\n error: '项目名称不能为空'\n }, { status: 400 });\n }\n\n const workspacePath = WORKSPACE_CONFIG.WORKSPACE_ROOT;\n const projectPath = join(workspacePath, projectName);\n\n // 检查项目目录是否存在\n try {\n await fs.access(projectPath);\n } catch {\n return NextResponse.json({\n success: false,\n error: '项目目录不存在'\n }, { status: 404 });\n }\n\n // 删除项目目录\n try {\n await fs.rm(projectPath, { recursive: true, force: true });\n console.log(`手动清理项目成功: ${projectPath}`);\n \n return NextResponse.json({\n success: true,\n message: `项目 ${projectName} 已成功清理`\n });\n } catch (error) {\n console.error(`清理项目失败 ${projectPath}:`, error);\n return NextResponse.json({\n success: false,\n error: `清理项目失败: ${error instanceof Error ? error.message : String(error)}`\n }, { status: 500 });\n }\n\n } catch (error) {\n console.error('清理项目请求处理失败:', error);\n return NextResponse.json({\n success: false,\n error: '服务器内部错误'\n }, { status: 500 });\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":"y+CAAA,IAAA,EAAA,EAAA,CAAA,CAAA,OACA,EAAA,EAAA,CAAA,CAAA,OAKO,IAAM,EAAmB,CAE9B,eAAgB,CAAA,EAAA,EAAA,IAAA,AAAG,EAAE,CAAA,EAAA,EAAA,OAAM,AAAN,IAAW,YAAa,EAA7B,WAAK,MAGrB,YAAa,IAGb,sBAAuB,KAAK,GAAG,CAAC,EAAG,KAAK,GAAG,CAAC,CAAA,EAAA,EAAA,IAAG,AAAH,IAAO,MAAM,CAAE,IAG3D,iBAH4C,EAGxB,CACtB,EAEa,EAAsB,CAAA,EAAA,EAAA,IAAA,AAAG,EAAE,CAAA,EAAA,EAAA,OAAA,AAAM,IAAK,cAAhB,UAuC5B,CAvCiC,GAuC5B,EAAA,SAAA,CAAA,6JAAA,mNC3DZ,IAAA,EAAA,EAAA,CAAA,CAAA,OACA,EAAA,EAAA,CAAA,CAAA,OACA,EAAA,EAAA,CAAA,CAAA,OACA,EAAA,EAAA,CAAA,CAAA,OAEO,eAAe,EAAK,CAAoB,EAC7C,GAAI,CACF,GAAM,aAAE,CAAW,CAAE,CAAG,MAAM,EAAQ,IAAI,GAE1C,GAAI,CAAC,GAAsC,UAAvB,AAAiC,OAA1B,EACzB,OAAO,EAAA,YAAY,CAAC,IAAI,CAAC,CACvB,SAAS,EACT,MAAO,AAFF,UAGP,EAAG,CAAE,OAAQ,GAAI,GAGnB,IAAM,EAAgB,EAAA,gBAAgB,CAAC,cAAc,CAC/C,EAAc,CAAA,CADE,CACF,EAAA,IAAA,AAAG,EAAE,EAAe,GAGxC,GAAI,CACF,MAAM,EAAA,QAAE,CAAC,IAJS,EAIH,CAAC,EAClB,CAAE,KAAM,CACN,OAAO,EAAA,EAFD,UAEa,CAAC,IAAI,CAAC,CACvB,QAAS,GACT,MAFK,AAEE,SACT,EAAG,CAAE,OAAQ,GAAI,EACnB,CAGA,GAAI,CAIF,OAHA,MAAM,EAAA,QAAE,CAAC,EAAE,CAAC,EAAa,CAAE,UAAW,GAAM,OAAO,CAAK,AAAlD,GACN,QAAQ,GAAG,CAAC,CAAC,UAAU,EAAE,EAAA,CAAa,EAE/B,EAAA,YAAY,CAAC,IAAI,CAAC,CACvB,SAAS,EACT,MAFK,EAEI,CAAC,GAAG,EAAE,EAAY,MAAM,CAAC,AACpC,EACF,CAAE,MAAO,EAAO,CAEd,OADA,QAAQ,KAAK,CAAC,CAAC,OAAO,EAAE,EAAY,CAAC,CAAC,CAAE,GACjC,EAAA,YAAY,CAAC,IAAI,CAAC,CACvB,SAAS,EACT,MAFK,AAEE,CAAC,QAAQ,EAAE,aAAiB,MAAQ,EAAM,OAAO,CAAG,OAAO,GAAA,CAAQ,AAC5E,EAAG,CAAE,OAAQ,GAAI,EACnB,CAEF,CAAE,MAAO,EAAO,CAEd,OADA,QAAQ,KAAK,CAAC,cAAe,GACtB,EAAA,YAAY,CAAC,IAAI,CAAC,CACvB,SAAS,EACT,MAAO,AAFF,SAGP,EAAG,CAAE,OAAQ,GAAI,EACnB,CACF,gKCrDA,IAAA,EAGO,EAAA,CAFLA,AAEK,CAAA,OACP,EAA0B,EAAyB,CAA1CC,AAA0C,CAAA,GAAA,EAH9B,EAIrB,CADkB,CAD2C,AAEnB,EAAA,CAAjCC,AAAiC,CAAA,AAFnC,GACmB,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,6BACNC,SAAU,uBACVC,SAAU,QACVC,WAAY,EACd,EACAC,iBAAkB,iEAClBC,iBAXF,CAA0B,WAYxBV,CACF,GAKM,kBAAEW,CAAgB,sBAAEC,CAAoB,aAAEC,CAAW,CAAE,CAAGZ,EAEhE,SAASH,IACP,MAAA,CAAA,EAAA,EAAOC,UAAAA,EAAY,kBACjBY,uBACAC,CACF,EACF","ignoreList":[2]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["turbopack:///[project]/packages/server/src/lib/workspace-types.ts","turbopack:///[project]/packages/server/src/lib/workspace-config.ts","turbopack:///[project]/packages/server/src/app/api/check-mock-intercept/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 projectName?: 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}\n","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 projectName?: string;\n targetDir: string;\n timeout: number;\n onProgress?: (progress: number, message: string) => void;\n onError?: (error: string) => void;\n}\n","import { NextRequest, NextResponse } from 'next/server';\nimport { getProjectsConfig } from '@/lib/workspace-config';\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 mockingIntercept: projectConfig.mockingIntercept || false,\n mockOpen: projectConfig.mockOpen || false,\n },\n });\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : '获取Mock拦截状态失败';\n console.error('获取Mock拦截状态失败:', 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":"+VAAA,IAAA,EAAA,EAAA,CAAA,CAAA,OACA,EAAA,EAAA,CAAA,CAAA,OAKO,IAAM,EAAmB,CAE9B,eAAgB,GAAA,EAAA,IAAA,AAAG,EAAE,CAAA,EAAA,EAAA,OAAM,AAAN,IAAW,YAAa,EAA7B,WAAK,MAGrB,YAAa,IAGb,sBAAuB,KAAK,GAAG,CAAC,EAAG,KAAK,GAAG,CAAC,CAAA,EAAA,EAAA,IAAG,AAAH,IAAO,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,s3CC/CZ,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,MAAM,AAH4B,EAGT,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,SAAQ,AAAR,EAAU,EAAgB,KAAK,SAAS,CAAC,EAAQ,KAAM,AAAvD,GAA2D,SACjE,MAAM,CAAA,EAAA,EAAA,MAAA,AAAK,EAAE,EAAgB,EAAA,mBAAmB,CAClD,CAAE,EADM,IACC,EAAO,CAEd,MADA,AAF6B,QAErB,KAAK,CAAC,cAAe,GACvB,AAAI,MAAM,WAClB,CACF,CAKO,IAAK,EAAA,SAAA,CAAA,mIAAA,yHCjDZ,IAAA,EAAA,EAAA,CAAA,CAAA,OACA,EAAA,EAAA,CAAA,CAAA,OAEO,eAAe,EAAI,CAAoB,EAC5C,GAAI,CACF,GAAM,cAAE,CAAY,CAAE,CAAG,IAAI,IAAI,EAAQ,GAAG,EACtC,EAAc,EAAa,GAAG,CAAC,WAErC,GAAI,CAAC,EACH,OAAO,EAAA,EADS,UACG,CAAC,IAAI,CACtB,CAAE,QAAS,GAAO,MAAO,AADpB,UAC+B,EACpC,CAAE,OAAQ,GAAI,GAKlB,IAAM,EAAiB,MAAM,CAAA,EAAA,EAAA,iBAAA,AAAgB,IAG7C,GAAI,CAAC,CAAc,CAAC,EAAY,CAC9B,CADgC,KAHL,CAIpB,EAAA,YAAY,CAAC,IAAI,CACtB,CAAE,SAAS,EAAO,MADb,AACoB,CAAC,GAAG,EAAE,EAAY,IAAI,CAAC,AAAC,EACjD,CAAE,OAAQ,GAAI,GAIlB,IAAM,EAAgB,CAAc,CAAC,EAAY,CAEjD,OAAO,EAAA,YAAY,CAAC,IAAI,CAAC,CACvB,SAAS,EACT,KAAM,CAFD,AAGH,iBAAkB,EAAc,gBAAgB,GAAI,EACpD,SAAU,EAAc,QAAQ,EAAI,EACtC,CACF,EACF,CAAE,MAAO,EAAO,CACd,IAAM,EACJ,aAAiB,MAAQ,EAAM,OAAO,CAAG,eAE3C,OADA,QAAQ,KAAK,CAAC,gBAAiB,GACxB,EAAA,YAAY,CAAC,IAAI,CACtB,CAAE,QAAS,GAAO,MADb,AACoB,CAAa,EACtC,CAAE,OAAQ,GAAI,EAElB,CACF,gKC5CA,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,CAAA,AAFjBC,EAEXC,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,kBAAEW,CAAgB,sBAAEC,CAAoB,aAAEC,CAAW,CAAE,CAAGZ,EAEhE,SAASH,IACP,MAAA,CAAA,EAAA,EAAOC,UAAAA,EAAY,kBACjBY,uBACAC,CACF,EACF","ignoreList":[3]}
|
|
1
|
+
{"version":3,"sources":["turbopack:///[project]/packages/server/src/lib/workspace-types.ts","turbopack:///[project]/packages/server/src/lib/workspace-config.ts","turbopack:///[project]/packages/server/src/app/api/check-mock-intercept/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 ApiProxyRewrite {\n mode: 'none' | 'remove' | 'replace';\n targetPrefix?: string;\n}\n\nexport interface ApiProxyItem {\n prefix: string;\n proxyKey?: string;\n currentProxy: string;\n proxyEnv: {\n [key: string]: string;\n };\n rewrite?: ApiProxyRewrite;\n}\n\nexport interface ProjectConfig {\n repo: string;\n mockingIntercept?: boolean;\n mockOpen?: boolean;\n envs: {\n [envName: string]: {\n host: string;\n envFileName: string;\n apiProxies: ApiProxyItem[];\n subApps?: string[];\n startCommand?: 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 projectName?: 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}\n","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 projectName?: string;\n targetDir: string;\n timeout: number;\n onProgress?: (progress: number, message: string) => void;\n onError?: (error: string) => void;\n}\n","import { NextRequest, NextResponse } from 'next/server';\nimport { getProjectsConfig } from '@/lib/workspace-config';\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 mockingIntercept: projectConfig.mockingIntercept || false,\n mockOpen: projectConfig.mockOpen || false,\n },\n });\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : '获取Mock拦截状态失败';\n console.error('获取Mock拦截状态失败:', 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":[3]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["turbopack:///[project]/packages/server/src/lib/workspace-types.ts","turbopack:///[project]/packages/server/src/lib/workspace-config.ts","turbopack:///[project]/packages/server/src/app/api/process/status/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 projectName?: 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}\n","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 projectName?: string;\n targetDir: string;\n timeout: number;\n onProgress?: (progress: number, message: string) => void;\n onError?: (error: string) => void;\n}\n","import { NextRequest, NextResponse } from 'next/server';\nimport path from 'path';\nimport fs from 'fs/promises';\nimport os from 'os';\nimport { exec } from 'child_process';\nimport { promisify } from 'util';\nimport { getProjectsConfig } from '@/lib/workspace-config';\n\nconst execAsync = promisify(exec);\n\n// 获取进程存储文件路径\nfunction getProcessStorePath() {\n return path.join(os.homedir(), '.prime-processes.json');\n}\n\n// 检查进程是否仍在运行\nasync function isProcessRunning(pid: number): Promise<boolean> {\n try {\n // 在Unix系统上,使用kill -0来检查进程是否存在\n if (process.platform !== 'win32') {\n process.kill(pid, 0);\n return true;\n } else {\n // 在Windows上使用tasklist命令\n const { stdout } = await execAsync(`tasklist /FI \"PID eq ${pid}\"`);\n return stdout.includes(pid.toString());\n }\n } catch {\n return false;\n }\n}\n\n// 检查端口是否被占用\nasync function isPortInUse(port: string): Promise<boolean> {\n try {\n const portNum = parseInt(port);\n if (isNaN(portNum)) return false;\n\n if (process.platform !== 'win32') {\n // Unix系统使用lsof\n try {\n const { stdout } = await execAsync(`lsof -i :${port} -t`);\n return stdout.trim().length > 0;\n } catch {\n return false;\n }\n } else {\n // Windows系统使用netstat\n const { stdout } = await execAsync(`netstat -ano | findstr :${port}`);\n return stdout.includes(`:${port}`);\n }\n } catch {\n return false;\n }\n}\n\nexport async function GET(request: NextRequest) {\n try {\n const { searchParams } = new URL(request.url);\n const projectName = searchParams.get('projectName');\n const envName = searchParams.get('envName');\n\n // 如果提供了项目名和环境名,返回特定进程状态\n if (projectName && envName) {\n const processKey = `${projectName}-${envName}`;\n \n // 尝试从存储的进程信息中读取\n try {\n const processInfoContent = await fs.readFile(getProcessStorePath(), 'utf-8');\n const processInfoList = JSON.parse(processInfoContent);\n const processInfo = processInfoList.find((p: { key: string; pid: number; port: string; startTime: string }) => p.key === processKey);\n\n if (processInfo) {\n // 检查进程是否仍在运行\n const isRunning = await isProcessRunning(processInfo.pid);\n const portInUse = processInfo.port ? await isPortInUse(processInfo.port) : false;\n\n return NextResponse.json({\n success: true,\n data: {\n running: isRunning,\n pid: processInfo.pid,\n startTime: processInfo.startTime,\n port: processInfo.port,\n portInUse\n }\n });\n }\n } catch {\n // 文件不存在或读取失败\n }\n\n // 如果没有找到进程信息,检查端口是否被占用\n // 读取项目配置获取端口信息\n try {\n const config = await getProjectsConfig();\n const project = config[projectName];\n if (project && project.envs && project.envs[envName]) {\n const port = project.envs[envName].host?.split(':').pop();\n if (port) {\n const portInUse = await isPortInUse(port);\n return NextResponse.json({\n success: true,\n data: {\n running: portInUse,\n portInUse,\n port\n }\n });\n }\n }\n } catch {\n // 配置文件读取失败\n }\n\n return NextResponse.json({\n success: true,\n data: {\n running: false\n }\n });\n }\n\n // 如果没有提供参数,返回所有进程状态\n const allProcesses: {\n key: string;\n projectName: string;\n envName: string;\n running: boolean;\n pid: number;\n startTime: string;\n port: string;\n portInUse: boolean;\n }[] = [];\n \n try {\n const processInfoContent = await fs.readFile(getProcessStorePath(), 'utf-8');\n const processInfoList = JSON.parse(processInfoContent);\n\n for (const processInfo of processInfoList) {\n const isRunning = await isProcessRunning(processInfo.pid);\n const portInUse = processInfo.port ? await isPortInUse(processInfo.port) : false;\n \n allProcesses.push({\n key: processInfo.key,\n projectName: processInfo.projectName,\n envName: processInfo.envName,\n running: isRunning,\n pid: processInfo.pid,\n startTime: processInfo.startTime,\n port: processInfo.port,\n portInUse\n });\n }\n } catch {\n // 文件不存在或读取失败,返回空数组\n }\n\n return NextResponse.json({\n success: true,\n data: allProcesses\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}","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":[3]}
|
|
1
|
+
{"version":3,"sources":["turbopack:///[project]/packages/server/src/lib/workspace-types.ts","turbopack:///[project]/packages/server/src/lib/workspace-config.ts","turbopack:///[project]/packages/server/src/app/api/process/status/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 ApiProxyRewrite {\n mode: 'none' | 'remove' | 'replace';\n targetPrefix?: string;\n}\n\nexport interface ApiProxyItem {\n prefix: string;\n proxyKey?: string;\n currentProxy: string;\n proxyEnv: {\n [key: string]: string;\n };\n rewrite?: ApiProxyRewrite;\n}\n\nexport interface ProjectConfig {\n repo: string;\n mockingIntercept?: boolean;\n mockOpen?: boolean;\n envs: {\n [envName: string]: {\n host: string;\n envFileName: string;\n apiProxies: ApiProxyItem[];\n subApps?: string[];\n startCommand?: 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 projectName?: 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}\n","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 projectName?: string;\n targetDir: string;\n timeout: number;\n onProgress?: (progress: number, message: string) => void;\n onError?: (error: string) => void;\n}\n","import { NextRequest, NextResponse } from 'next/server';\nimport path from 'path';\nimport fs from 'fs/promises';\nimport os from 'os';\nimport { exec } from 'child_process';\nimport { promisify } from 'util';\nimport { getProjectsConfig } from '@/lib/workspace-config';\n\nconst execAsync = promisify(exec);\n\n// 获取进程存储文件路径\nfunction getProcessStorePath() {\n return path.join(os.homedir(), '.prime-processes.json');\n}\n\n// 检查进程是否仍在运行\nasync function isProcessRunning(pid: number): Promise<boolean> {\n try {\n // 在Unix系统上,使用kill -0来检查进程是否存在\n if (process.platform !== 'win32') {\n process.kill(pid, 0);\n return true;\n } else {\n // 在Windows上使用tasklist命令\n const { stdout } = await execAsync(`tasklist /FI \"PID eq ${pid}\"`);\n return stdout.includes(pid.toString());\n }\n } catch {\n return false;\n }\n}\n\n// 检查端口是否被占用\nasync function isPortInUse(port: string): Promise<boolean> {\n try {\n const portNum = parseInt(port);\n if (isNaN(portNum)) return false;\n\n if (process.platform !== 'win32') {\n // Unix系统使用lsof\n try {\n const { stdout } = await execAsync(`lsof -i :${port} -t`);\n return stdout.trim().length > 0;\n } catch {\n return false;\n }\n } else {\n // Windows系统使用netstat\n const { stdout } = await execAsync(`netstat -ano | findstr :${port}`);\n return stdout.includes(`:${port}`);\n }\n } catch {\n return false;\n }\n}\n\nexport async function GET(request: NextRequest) {\n try {\n const { searchParams } = new URL(request.url);\n const projectName = searchParams.get('projectName');\n const envName = searchParams.get('envName');\n\n // 如果提供了项目名和环境名,返回特定进程状态\n if (projectName && envName) {\n const processKey = `${projectName}-${envName}`;\n \n // 尝试从存储的进程信息中读取\n try {\n const processInfoContent = await fs.readFile(getProcessStorePath(), 'utf-8');\n const processInfoList = JSON.parse(processInfoContent);\n const processInfo = processInfoList.find((p: { key: string; pid: number; port: string; startTime: string }) => p.key === processKey);\n\n if (processInfo) {\n // 检查进程是否仍在运行\n const isRunning = await isProcessRunning(processInfo.pid);\n const portInUse = processInfo.port ? await isPortInUse(processInfo.port) : false;\n\n return NextResponse.json({\n success: true,\n data: {\n running: isRunning,\n pid: processInfo.pid,\n startTime: processInfo.startTime,\n port: processInfo.port,\n portInUse\n }\n });\n }\n } catch {\n // 文件不存在或读取失败\n }\n\n // 如果没有找到进程信息,检查端口是否被占用\n // 读取项目配置获取端口信息\n try {\n const config = await getProjectsConfig();\n const project = config[projectName];\n if (project && project.envs && project.envs[envName]) {\n const port = project.envs[envName].host?.split(':').pop();\n if (port) {\n const portInUse = await isPortInUse(port);\n return NextResponse.json({\n success: true,\n data: {\n running: portInUse,\n portInUse,\n port\n }\n });\n }\n }\n } catch {\n // 配置文件读取失败\n }\n\n return NextResponse.json({\n success: true,\n data: {\n running: false\n }\n });\n }\n\n // 如果没有提供参数,返回所有进程状态\n const allProcesses: {\n key: string;\n projectName: string;\n envName: string;\n running: boolean;\n pid: number;\n startTime: string;\n port: string;\n portInUse: boolean;\n }[] = [];\n \n try {\n const processInfoContent = await fs.readFile(getProcessStorePath(), 'utf-8');\n const processInfoList = JSON.parse(processInfoContent);\n\n for (const processInfo of processInfoList) {\n const isRunning = await isProcessRunning(processInfo.pid);\n const portInUse = processInfo.port ? await isPortInUse(processInfo.port) : false;\n \n allProcesses.push({\n key: processInfo.key,\n projectName: processInfo.projectName,\n envName: processInfo.envName,\n running: isRunning,\n pid: processInfo.pid,\n startTime: processInfo.startTime,\n port: processInfo.port,\n portInUse\n });\n }\n } catch {\n // 文件不存在或读取失败,返回空数组\n }\n\n return NextResponse.json({\n success: true,\n data: allProcesses\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}","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":[3]}
|