refactor: standardize code formatting and linting configuration

- Replace .eslintrc.js with .eslintrc.cjs for better ES module compatibility
- Add .prettierrc configuration for consistent code formatting
- Update package.json with new lint and format scripts
- Add nodemon.json for development hot reloading configuration
- Standardize code formatting across all JavaScript and Vue files
- Update web admin SPA with improved linting rules and formatting
- Add prettier configuration to web admin SPA

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
千羽
2025-08-07 18:19:31 +09:00
parent 4a0eba117c
commit 8a74bf5afe
124 changed files with 20878 additions and 18757 deletions

View File

@@ -1,235 +1,232 @@
#!/usr/bin/env node
const { spawn, exec } = require('child_process');
const fs = require('fs');
const path = require('path');
const process = require('process');
const { spawn, exec } = require('child_process')
const fs = require('fs')
const path = require('path')
const process = require('process')
const PID_FILE = path.join(__dirname, '..', 'claude-relay-service.pid');
const LOG_FILE = path.join(__dirname, '..', 'logs', 'service.log');
const ERROR_LOG_FILE = path.join(__dirname, '..', 'logs', 'service-error.log');
const APP_FILE = path.join(__dirname, '..', 'src', 'app.js');
const PID_FILE = path.join(__dirname, '..', 'claude-relay-service.pid')
const LOG_FILE = path.join(__dirname, '..', 'logs', 'service.log')
const ERROR_LOG_FILE = path.join(__dirname, '..', 'logs', 'service-error.log')
const APP_FILE = path.join(__dirname, '..', 'src', 'app.js')
class ServiceManager {
constructor() {
this.ensureLogDir();
constructor() {
this.ensureLogDir()
}
ensureLogDir() {
const logDir = path.dirname(LOG_FILE)
if (!fs.existsSync(logDir)) {
fs.mkdirSync(logDir, { recursive: true })
}
}
getPid() {
try {
if (fs.existsSync(PID_FILE)) {
const pid = parseInt(fs.readFileSync(PID_FILE, 'utf8').trim())
return pid
}
} catch (error) {
console.error('读取PID文件失败:', error.message)
}
return null
}
isProcessRunning(pid) {
try {
process.kill(pid, 0)
return true
} catch (error) {
return false
}
}
writePid(pid) {
try {
fs.writeFileSync(PID_FILE, pid.toString())
console.log(`✅ PID ${pid} 已保存到 ${PID_FILE}`)
} catch (error) {
console.error('写入PID文件失败:', error.message)
}
}
removePidFile() {
try {
if (fs.existsSync(PID_FILE)) {
fs.unlinkSync(PID_FILE)
console.log('🗑️ 已清理PID文件')
}
} catch (error) {
console.error('清理PID文件失败:', error.message)
}
}
getStatus() {
const pid = this.getPid()
if (pid && this.isProcessRunning(pid)) {
return { running: true, pid }
}
return { running: false, pid: null }
}
start(daemon = false) {
const status = this.getStatus()
if (status.running) {
console.log(`⚠️ 服务已在运行中 (PID: ${status.pid})`)
return false
}
ensureLogDir() {
const logDir = path.dirname(LOG_FILE);
if (!fs.existsSync(logDir)) {
fs.mkdirSync(logDir, { recursive: true });
}
}
console.log('🚀 启动 Claude Relay Service...')
getPid() {
try {
if (fs.existsSync(PID_FILE)) {
const pid = parseInt(fs.readFileSync(PID_FILE, 'utf8').trim());
return pid;
}
} catch (error) {
console.error('读取PID文件失败:', error.message);
}
return null;
}
if (daemon) {
// 后台运行模式 - 使用nohup实现真正的后台运行
const { exec: execChild } = require('child_process')
isProcessRunning(pid) {
try {
process.kill(pid, 0);
return true;
} catch (error) {
return false;
}
}
const command = `nohup node "${APP_FILE}" > "${LOG_FILE}" 2> "${ERROR_LOG_FILE}" & echo $!`
writePid(pid) {
try {
fs.writeFileSync(PID_FILE, pid.toString());
console.log(`✅ PID ${pid} 已保存到 ${PID_FILE}`);
} catch (error) {
console.error('写入PID文件失败:', error.message);
}
}
removePidFile() {
try {
if (fs.existsSync(PID_FILE)) {
fs.unlinkSync(PID_FILE);
console.log('🗑️ 已清理PID文件');
}
} catch (error) {
console.error('清理PID文件失败:', error.message);
}
}
getStatus() {
const pid = this.getPid();
if (pid && this.isProcessRunning(pid)) {
return { running: true, pid };
}
return { running: false, pid: null };
}
start(daemon = false) {
const status = this.getStatus();
if (status.running) {
console.log(`⚠️ 服务已在运行中 (PID: ${status.pid})`);
return false;
execChild(command, (error, stdout) => {
if (error) {
console.error('❌ 后台启动失败:', error.message)
return
}
console.log('🚀 启动 Claude Relay Service...');
if (daemon) {
// 后台运行模式 - 使用nohup实现真正的后台运行
const { exec } = require('child_process');
const command = `nohup node "${APP_FILE}" > "${LOG_FILE}" 2> "${ERROR_LOG_FILE}" & echo $!`;
exec(command, (error, stdout, stderr) => {
if (error) {
console.error('❌ 后台启动失败:', error.message);
return;
}
const pid = parseInt(stdout.trim());
if (pid && !isNaN(pid)) {
this.writePid(pid);
console.log(`🔄 服务已在后台启动 (PID: ${pid})`);
console.log(`📝 日志文件: ${LOG_FILE}`);
console.log(`❌ 错误日志: ${ERROR_LOG_FILE}`);
console.log('✅ 终端现在可以安全关闭');
} else {
console.error('❌ 无法获取进程ID');
}
});
// 给exec一点时间执行
setTimeout(() => {
process.exit(0);
}, 1000);
const pid = parseInt(stdout.trim())
if (pid && !isNaN(pid)) {
this.writePid(pid)
console.log(`🔄 服务已在后台启动 (PID: ${pid})`)
console.log(`📝 日志文件: ${LOG_FILE}`)
console.log(`❌ 错误日志: ${ERROR_LOG_FILE}`)
console.log('✅ 终端现在可以安全关闭')
} else {
// 前台运行模式
const child = spawn('node', [APP_FILE], {
stdio: 'inherit'
});
console.error('❌ 无法获取进程ID')
}
})
console.log(`🔄 服务已启动 (PID: ${child.pid})`);
this.writePid(child.pid);
// 给exec一点时间执行
setTimeout(() => {
process.exit(0)
}, 1000)
} else {
// 前台运行模式
const child = spawn('node', [APP_FILE], {
stdio: 'inherit'
})
// 监听进程退出
child.on('exit', (code, signal) => {
this.removePidFile();
if (code !== 0) {
console.log(`💥 进程退出 (代码: ${code}, 信号: ${signal})`);
}
});
console.log(`🔄 服务已启动 (PID: ${child.pid})`)
child.on('error', (error) => {
console.error('❌ 启动失败:', error.message);
this.removePidFile();
});
this.writePid(child.pid)
// 监听进程退出
child.on('exit', (code, signal) => {
this.removePidFile()
if (code !== 0) {
console.log(`💥 进程退出 (代码: ${code}, 信号: ${signal})`)
}
})
child.on('error', (error) => {
console.error('❌ 启动失败:', error.message)
this.removePidFile()
})
}
return true
}
stop() {
const status = this.getStatus()
if (!status.running) {
console.log('⚠️ 服务未在运行')
this.removePidFile() // 清理可能存在的过期PID文件
return false
}
console.log(`🛑 停止服务 (PID: ${status.pid})...`)
try {
// 优雅关闭先发送SIGTERM
process.kill(status.pid, 'SIGTERM')
// 等待进程退出
let attempts = 0
const maxAttempts = 30 // 30秒超时
const checkExit = setInterval(() => {
attempts++
if (!this.isProcessRunning(status.pid)) {
clearInterval(checkExit)
console.log('✅ 服务已停止')
this.removePidFile()
return
}
return true;
}
stop() {
const status = this.getStatus();
if (!status.running) {
console.log('⚠️ 服务未在运行');
this.removePidFile(); // 清理可能存在的过期PID文件
return false;
if (attempts >= maxAttempts) {
clearInterval(checkExit)
console.log('⚠️ 优雅关闭超时,强制终止进程...')
try {
process.kill(status.pid, 'SIGKILL')
console.log('✅ 服务已强制停止')
} catch (error) {
console.error('❌ 强制停止失败:', error.message)
}
this.removePidFile()
}
}, 1000)
} catch (error) {
console.error('❌ 停止服务失败:', error.message)
this.removePidFile()
return false
}
console.log(`🛑 停止服务 (PID: ${status.pid})...`);
return true
}
try {
// 优雅关闭先发送SIGTERM
process.kill(status.pid, 'SIGTERM');
restart(daemon = false) {
console.log('🔄 重启服务...')
// 等待进程退出
let attempts = 0;
const maxAttempts = 30; // 30秒超时
// 等待停止完成
setTimeout(() => {
this.start(daemon)
}, 2000)
const checkExit = setInterval(() => {
attempts++;
if (!this.isProcessRunning(status.pid)) {
clearInterval(checkExit);
console.log('✅ 服务已停止');
this.removePidFile();
return;
}
return true
}
if (attempts >= maxAttempts) {
clearInterval(checkExit);
console.log('⚠️ 优雅关闭超时,强制终止进程...');
try {
process.kill(status.pid, 'SIGKILL');
console.log('✅ 服务已强制停止');
} catch (error) {
console.error('❌ 强制停止失败:', error.message);
}
this.removePidFile();
}
}, 1000);
status() {
const status = this.getStatus()
if (status.running) {
console.log(`✅ 服务正在运行 (PID: ${status.pid})`)
} catch (error) {
console.error('❌ 停止服务失败:', error.message);
this.removePidFile();
return false;
// 显示进程信息
exec(`ps -p ${status.pid} -o pid,ppid,pcpu,pmem,etime,cmd --no-headers`, (error, stdout) => {
if (!error && stdout.trim()) {
console.log('\n📊 进程信息:')
console.log('PID\tPPID\tCPU%\tMEM%\tTIME\t\tCOMMAND')
console.log(stdout.trim())
}
return true;
})
} else {
console.log('❌ 服务未运行')
}
return status.running
}
restart(daemon = false) {
console.log('🔄 重启服务...');
const stopResult = this.stop();
// 等待停止完成
setTimeout(() => {
this.start(daemon);
}, 2000);
return true;
}
logs(lines = 50) {
console.log(`📖 最近 ${lines} 行日志:\n`)
status() {
const status = this.getStatus();
if (status.running) {
console.log(`✅ 服务正在运行 (PID: ${status.pid})`);
// 显示进程信息
exec(`ps -p ${status.pid} -o pid,ppid,pcpu,pmem,etime,cmd --no-headers`, (error, stdout) => {
if (!error && stdout.trim()) {
console.log('\n📊 进程信息:');
console.log('PID\tPPID\tCPU%\tMEM%\tTIME\t\tCOMMAND');
console.log(stdout.trim());
}
});
} else {
console.log('❌ 服务未运行');
}
return status.running;
}
exec(`tail -n ${lines} ${LOG_FILE}`, (error, stdout) => {
if (error) {
console.error('读取日志失败:', error.message)
return
}
console.log(stdout)
})
}
logs(lines = 50) {
console.log(`📖 最近 ${lines} 行日志:\n`);
exec(`tail -n ${lines} ${LOG_FILE}`, (error, stdout) => {
if (error) {
console.error('读取日志失败:', error.message);
return;
}
console.log(stdout);
});
}
help() {
console.log(`
help() {
console.log(`
🔧 Claude Relay Service 进程管理器
用法: npm run service <command> [options]
@@ -281,55 +278,56 @@ class ServiceManager {
PID文件: ${PID_FILE}
日志文件: ${LOG_FILE}
错误日志: ${ERROR_LOG_FILE}
`);
}
`)
}
}
// 主程序
function main() {
const manager = new ServiceManager();
const args = process.argv.slice(2);
const command = args[0];
const isDaemon = args.includes('-d') || args.includes('--daemon');
const manager = new ServiceManager()
const args = process.argv.slice(2)
const command = args[0]
const isDaemon = args.includes('-d') || args.includes('--daemon')
switch (command) {
case 'start':
case 's':
manager.start(isDaemon);
break;
case 'stop':
case 'halt':
manager.stop();
break;
case 'restart':
case 'r':
manager.restart(isDaemon);
break;
case 'status':
case 'st':
manager.status();
break;
case 'logs':
case 'log':
case 'l':
const lines = parseInt(args[1]) || 50;
manager.logs(lines);
break;
case 'help':
case '--help':
case '-h':
case 'h':
manager.help();
break;
default:
console.log('❌ 未知命令:', command);
manager.help();
process.exit(1);
switch (command) {
case 'start':
case 's':
manager.start(isDaemon)
break
case 'stop':
case 'halt':
manager.stop()
break
case 'restart':
case 'r':
manager.restart(isDaemon)
break
case 'status':
case 'st':
manager.status()
break
case 'logs':
case 'log':
case 'l': {
const lines = parseInt(args[1]) || 50
manager.logs(lines)
break
}
case 'help':
case '--help':
case '-h':
case 'h':
manager.help()
break
default:
console.log('❌ 未知命令:', command)
manager.help()
process.exit(1)
}
}
if (require.main === module) {
main();
main()
}
module.exports = ServiceManager;
module.exports = ServiceManager