130 lines
3.5 KiB
JavaScript
130 lines
3.5 KiB
JavaScript
import path from "path";
|
||
import fs from "fs";
|
||
import { log } from "../log/logUtils.js";
|
||
import { BusinessError, FileError, ResourceError } from "../error/errorHandler.js";
|
||
import {
|
||
isProjectStarting,
|
||
addStartingProject,
|
||
removeStartingProject,
|
||
startDev_NonBlocking,
|
||
} from "./processManager.js";
|
||
import ERROR_CODES from "../error/errorCodes.js";
|
||
import { stopDevServer } from "./stopDevUtils.js";
|
||
import { removeNodeModules } from "../buildDependency/dependencyManager.js";
|
||
import { createPnpmNpmrc } from "../common/npmrcUtils.js";
|
||
import {
|
||
extractIsolationContext,
|
||
resolveProjectPath,
|
||
} from "../common/projectPathUtils.js";
|
||
|
||
// 重启开发服务器
|
||
async function restartDevServer(req, projectId) {
|
||
log(projectId, "INFO", "Start restarting development server", {
|
||
projectId,
|
||
requestId: req.requestId,
|
||
});
|
||
|
||
// 检查项目是否存在
|
||
const isolationContext = extractIsolationContext(req?.query || {});
|
||
const projectPath = resolveProjectPath(projectId, isolationContext);
|
||
const jsonFilePath = path.join(projectPath, "package.json");
|
||
const exists = fs.existsSync(jsonFilePath);
|
||
if (!exists) {
|
||
log(projectId, "WARN", "Project missing package.json file", {
|
||
projectId,
|
||
requestId: req.requestId,
|
||
});
|
||
throw new ResourceError("Project missing package.json file", {
|
||
projectId,
|
||
projectPath,
|
||
});
|
||
}
|
||
|
||
let jsonContent;
|
||
try {
|
||
jsonContent = JSON.parse(fs.readFileSync(jsonFilePath, "utf8"));
|
||
} catch (error) {
|
||
throw new FileError("package.json file format error", {
|
||
projectId,
|
||
jsonFilePath,
|
||
originalError: error.message,
|
||
});
|
||
}
|
||
|
||
const jsonScripts = jsonContent.scripts;
|
||
const devScript = jsonScripts.dev;
|
||
if (!devScript) {
|
||
log(projectId, "WARN", "Project missing dev script", {
|
||
projectId,
|
||
requestId: req.requestId,
|
||
});
|
||
throw new BusinessError("Project missing dev script", { projectId });
|
||
}
|
||
|
||
// 如果项目正在启动中,等待完成
|
||
// if (isProjectStarting(projectId)) {
|
||
// throw new BusinessError("Project is starting, please try again later", {
|
||
// projectId,
|
||
// code: ERROR_CODES.PROJECT_STARTING,
|
||
// });
|
||
// }
|
||
|
||
addStartingProject(projectId);
|
||
|
||
try {
|
||
// 1. 停止现有的开发服务器
|
||
const pidFromQuery = req.query.pid;
|
||
|
||
await stopDevServer(req, projectId, pidFromQuery, {
|
||
strict: false, // 非严格模式,停止失败不抛出异常
|
||
waitForStop: true, // 等待进程完全停止
|
||
});
|
||
|
||
// 2. 删除node_modules
|
||
log(projectId, "INFO", "Start deleting node_modules and lock file", {
|
||
projectId,
|
||
requestId: req.requestId,
|
||
});
|
||
await removeNodeModules(projectPath, projectId);
|
||
|
||
// 3. 创建.npmrc文件
|
||
log(projectId, "INFO", "Create .npmrc file", {
|
||
projectId,
|
||
requestId: req.requestId,
|
||
});
|
||
await createPnpmNpmrc(projectPath, projectId);
|
||
|
||
// 4. 启动dev服务器(依赖安装会在 startDev_NonBlocking 中执行)
|
||
log(projectId, "INFO", "Start starting dev server", {
|
||
projectId,
|
||
requestId: req.requestId,
|
||
});
|
||
|
||
const { pid, port: actualPort } = await startDev_NonBlocking({
|
||
req,
|
||
projectId,
|
||
projectPath,
|
||
devScript,
|
||
});
|
||
|
||
log(projectId, "INFO", "Dev server restart completed", {
|
||
projectId,
|
||
pid,
|
||
port: actualPort,
|
||
requestId: req.requestId,
|
||
});
|
||
|
||
return {
|
||
success: true,
|
||
message: "Development server restart successfully",
|
||
projectId,
|
||
pid,
|
||
port: actualPort,
|
||
};
|
||
} finally {
|
||
removeStartingProject(projectId);
|
||
}
|
||
}
|
||
|
||
export { restartDevServer };
|