diff --git a/scripts/GenerateWebAPI.ts b/scripts/GenerateWebAPI.ts index d47bedc..9cdaf81 100644 --- a/scripts/GenerateWebAPI.ts +++ b/scripts/GenerateWebAPI.ts @@ -1,6 +1,7 @@ import { spawn, exec, ChildProcess } from 'child_process'; import { promisify } from 'util'; import fetch from 'node-fetch'; +import * as fs from 'fs'; const execAsync = promisify(exec); @@ -166,7 +167,7 @@ async function stopServer(): Promise { } }); - // 设置超时,如果 5 秒内没有退出则强制终止 + // 设置超时,如果 3 秒内没有退出则强制终止 const timeoutPromise = new Promise((resolve) => { setTimeout(() => { if (serverProcess && !serverProcess.killed && serverProcess.exitCode === null) { @@ -174,7 +175,7 @@ async function stopServer(): Promise { serverProcess.kill('SIGKILL'); } resolve(); - }, 5000); + }, 3000); // 减少超时时间到3秒 }); await Promise.race([exitPromise, timeoutPromise]); @@ -184,22 +185,8 @@ async function stopServer(): Promise { } finally { serverProcess = null; - // 额外清理:确保没有遗留的 dotnet 进程 - try { - if (process.platform === 'win32') { - // Windows: 使用 taskkill 清理进程 - await execAsync('taskkill /F /IM dotnet.exe').catch(() => { - // 忽略错误,可能没有匹配的进程 - }); - } else { - // 只清理与我们项目相关的进程 - await execAsync('pkill -f "dotnet.*run.*--property:Configuration=Release"').catch(() => { - // 忽略错误,可能没有匹配的进程 - }); - } - } catch (cleanupError) { - // 忽略清理错误 - } + // 只有在进程可能没有正常退出时才执行清理 + // 移除自动清理逻辑,因为正常退出时不需要 } } @@ -238,7 +225,7 @@ async function stopWeb(): Promise { } }); - // 设置超时,如果 5 秒内没有退出则强制终止 + // 设置超时,如果 3 秒内没有退出则强制终止 const timeoutPromise = new Promise((resolve) => { setTimeout(() => { if (webProcess && !webProcess.killed && webProcess.exitCode === null) { @@ -246,7 +233,7 @@ async function stopWeb(): Promise { webProcess.kill('SIGKILL'); } resolve(); - }, 5000); + }, 3000); // 减少超时时间到3秒 }); await Promise.race([exitPromise, timeoutPromise]); @@ -256,22 +243,36 @@ async function stopWeb(): Promise { } finally { webProcess = null; - // 额外清理:确保没有遗留的 npm/node 进程 - try { - if (process.platform === 'win32') { - // Windows: 清理可能的 node 进程 - await execAsync('taskkill /F /IM node.exe').catch(() => { - // 忽略错误,可能没有匹配的进程 - }); - } else { - // 清理可能的 vite 进程 - await execAsync('pkill -f "vite"').catch(() => { - // 忽略错误,可能没有匹配的进程 - }); - } - } catch (cleanupError) { - // 忽略清理错误 + // 只有在进程可能没有正常退出时才执行清理 + // 移除自动清理逻辑,因为正常退出时不需要 + } +} + +async function postProcessApiClient(): Promise { + console.log('Post-processing API client...'); + try { + const filePath = 'src/APIClient.ts'; + + // 检查文件是否存在 + if (!fs.existsSync(filePath)) { + throw new Error(`API client file not found: ${filePath}`); } + + // 读取文件内容 + let content = fs.readFileSync(filePath, 'utf8'); + + // 替换 ArgumentException 中的 message 属性声明 + content = content.replace( + /(\s+)message!:\s*string;/g, + '$1declare message: string;' + ); + + // 写回文件 + fs.writeFileSync(filePath, content, 'utf8'); + + console.log('✓ API client post-processing completed'); + } catch (error) { + throw new Error(`Failed to post-process API client: ${error}`); } } @@ -281,6 +282,9 @@ async function generateApiClient(): Promise { const npxCommand = getCommand('npx'); await execAsync(`${npxCommand} nswag openapi2tsclient /input:http://localhost:5000/swagger/v1/swagger.json /output:src/APIClient.ts`); console.log('✓ API client generated successfully'); + + // 添加后处理步骤 + await postProcessApiClient(); } catch (error) { throw new Error(`Failed to generate API client: ${error}`); } @@ -323,11 +327,28 @@ async function main(): Promise { } } -// 改进的进程终止处理 +// 改进的进程终止处理 - 添加防重复执行 +let isCleaningUp = false; + const cleanup = async (signal: string) => { + if (isCleaningUp) { + console.log('Cleanup already in progress, ignoring signal'); + return; + } + + isCleaningUp = true; console.log(`\nReceived ${signal}, cleaning up...`); - await stopServer(); - await stopWeb(); + + try { + await Promise.all([ + stopServer(), + stopWeb() + ]); + } catch (error) { + console.error('Error during cleanup:', error); + } + + // 立即退出,不等待 process.exit(0); }; @@ -336,22 +357,55 @@ process.on('SIGTERM', () => cleanup('SIGTERM')); // 处理未捕获的异常 process.on('uncaughtException', async (error) => { + if (isCleaningUp) return; + console.error('❌ Uncaught exception:', error); - await stopServer(); - await stopWeb(); + isCleaningUp = true; + + try { + await Promise.all([ + stopServer(), + stopWeb() + ]); + } catch (cleanupError) { + console.error('Error during cleanup:', cleanupError); + } + process.exit(1); }); process.on('unhandledRejection', async (reason, promise) => { + if (isCleaningUp) return; + console.error('❌ Unhandled rejection at:', promise, 'reason:', reason); - await stopServer(); - await stopWeb(); + isCleaningUp = true; + + try { + await Promise.all([ + stopServer(), + stopWeb() + ]); + } catch (cleanupError) { + console.error('Error during cleanup:', cleanupError); + } + process.exit(1); }); main().catch(async (error) => { + if (isCleaningUp) return; + console.error('❌ Unhandled error:', error); - await stopServer(); - await stopWeb(); + isCleaningUp = true; + + try { + await Promise.all([ + stopServer(), + stopWeb() + ]); + } catch (cleanupError) { + console.error('Error during cleanup:', cleanupError); + } + process.exit(1); }); \ No newline at end of file