221 lines
6.0 KiB
JavaScript
221 lines
6.0 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
/**
|
|
* qiming-file-server CLI 入口
|
|
*
|
|
* 设计原则:
|
|
* - CLI 只负责参数解析与输出
|
|
* - 服务生命周期逻辑统一收敛到 serviceManager
|
|
*/
|
|
|
|
import { Command } from "commander";
|
|
import { createRequire } from "module";
|
|
import {
|
|
SERVICE_CONFIG,
|
|
startService,
|
|
stopService,
|
|
restartService,
|
|
getServiceStatus,
|
|
getPidFilePath,
|
|
formatUptime,
|
|
} from "./utils/serviceManager.js";
|
|
|
|
const esmRequire = createRequire(import.meta.url);
|
|
const version = typeof __BUILD_VERSION__ !== "undefined" ? __BUILD_VERSION__ : esmRequire("../package.json").version;
|
|
|
|
const program = new Command();
|
|
|
|
const colors = {
|
|
reset: '\x1b[0m',
|
|
red: '\x1b[31m',
|
|
green: '\x1b[32m',
|
|
yellow: '\x1b[33m',
|
|
blue: '\x1b[34m',
|
|
cyan: '\x1b[36m',
|
|
};
|
|
|
|
function log(message, color = 'reset') {
|
|
console.log(`${colors[color]}${message}${colors.reset}`);
|
|
}
|
|
|
|
function error(message) {
|
|
console.error(`${colors.red}ERROR: ${message}${colors.reset}`);
|
|
}
|
|
|
|
function success(message) {
|
|
console.log(`${colors.green}${message}${colors.reset}`);
|
|
}
|
|
|
|
function info(message) {
|
|
console.log(`${colors.blue}${message}${colors.reset}`);
|
|
}
|
|
|
|
/**
|
|
* 统一执行命令动作并设置退出码
|
|
* @param {Function} action 命令动作
|
|
* @returns {Function} commander action
|
|
*/
|
|
function runCommandAction(action) {
|
|
return async (...args) => {
|
|
try {
|
|
const result = await action(...args);
|
|
if (result && result.success === false) {
|
|
error(result.message || 'Command failed');
|
|
process.exitCode = 1;
|
|
} else {
|
|
process.exitCode = 0;
|
|
}
|
|
} catch (err) {
|
|
error(err?.message || 'Command failed with unexpected error');
|
|
process.exitCode = 1;
|
|
}
|
|
};
|
|
}
|
|
|
|
/**
|
|
* start 命令
|
|
*
|
|
* @param {Object} options - commander 参数
|
|
* @returns {Promise<Object>} 执行结果
|
|
*/
|
|
async function runStartCommand(options) {
|
|
const result = await startService({
|
|
env: options.env,
|
|
port: options.port,
|
|
config: options.config,
|
|
timeout: Number(options.timeout),
|
|
startTimeout: Number(options.startTimeout),
|
|
});
|
|
|
|
if (result.success) {
|
|
success(`Service started (PID: ${result.pid})`);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* stop 命令
|
|
*
|
|
* @param {Object} options - commander 参数
|
|
* @returns {Promise<Object>} 执行结果
|
|
*/
|
|
async function runStopCommand(options) {
|
|
const result = await stopService({
|
|
force: options.force,
|
|
timeout: Number(options.timeout),
|
|
});
|
|
if (result.success) {
|
|
success(result.message || 'Service stopped');
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* restart 命令
|
|
*
|
|
* @param {Object} options - commander 参数
|
|
* @returns {Promise<Object>} 执行结果
|
|
*/
|
|
async function runRestartCommand(options) {
|
|
const result = await restartService({
|
|
env: options.env,
|
|
port: options.port,
|
|
config: options.config,
|
|
timeout: Number(options.timeout),
|
|
startTimeout: Number(options.startTimeout),
|
|
});
|
|
if (result.success) {
|
|
success(result.message || 'Service restarted');
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* status 命令
|
|
*
|
|
* @returns {Object} 执行结果
|
|
*/
|
|
function runStatusCommand() {
|
|
const status = getServiceStatus();
|
|
|
|
info(`${SERVICE_CONFIG.name} service status:`);
|
|
console.log('');
|
|
console.log(` Service name: ${SERVICE_CONFIG.name}`);
|
|
console.log(` Running status: ${status.running ? 'Running' : 'Stopped'}`);
|
|
console.log(` Message: ${status.message}`);
|
|
console.log(` PID file: ${getPidFilePath()}`);
|
|
|
|
if (status.pidInfo) {
|
|
console.log(` Process ID: ${status.pidInfo.pid}`);
|
|
console.log(` Environment: ${status.pidInfo.env || 'Unknown'}`);
|
|
console.log(` Port: ${status.pidInfo.port || 'Unknown'}`);
|
|
console.log(` Version: ${status.pidInfo.version || version}`);
|
|
console.log(` Platform: ${status.pidInfo.platform || process.platform}`);
|
|
console.log(` Started at: ${status.pidInfo.startedAt || 'Unknown'}`);
|
|
console.log(` Uptime: ${formatUptime(status.pidInfo.startedAt)}`);
|
|
}
|
|
console.log('');
|
|
|
|
return {
|
|
success: status.running,
|
|
message: status.message,
|
|
};
|
|
}
|
|
|
|
// 主程序
|
|
function main() {
|
|
program
|
|
.name('qiming-file-server')
|
|
.description('Cross-platform file service deployment tool, supporting start/stop/restart/status')
|
|
.version(version, '-v, --version', 'Display version number')
|
|
.helpOption('-h, --help', 'Display help information');
|
|
|
|
program
|
|
.command('start').allowUnknownOption()
|
|
.description('Start service')
|
|
.option('--env <environment>', '环境: development|production|test', 'production')
|
|
.option('--port <port>', 'Service port')
|
|
.option('--config <path>', 'Custom configuration file path')
|
|
.option('--timeout <ms>', '停止旧进程等待超时(毫秒)', `${SERVICE_CONFIG.defaultStopTimeout}`)
|
|
.option('--start-timeout <ms>', '启动健康检查超时(毫秒)', `${SERVICE_CONFIG.defaultStartTimeout}`)
|
|
.action(runCommandAction(runStartCommand));
|
|
|
|
program
|
|
.command('stop')
|
|
.description('Stop service')
|
|
.option('--force', 'Force stop')
|
|
.option('--timeout <ms>', '停止服务等待超时(毫秒)', `${SERVICE_CONFIG.defaultStopTimeout}`)
|
|
.action(runCommandAction(runStopCommand));
|
|
|
|
program
|
|
.command('restart').allowUnknownOption()
|
|
.description('Restart service')
|
|
.option('--env <environment>', '环境: development|production|test', 'production')
|
|
.option('--port <port>', 'Service port')
|
|
.option('--config <path>', 'Custom configuration file path')
|
|
.option('--timeout <ms>', '停止旧进程等待超时(毫秒)', `${SERVICE_CONFIG.defaultStopTimeout}`)
|
|
.option('--start-timeout <ms>', '启动健康检查超时(毫秒)', `${SERVICE_CONFIG.defaultStartTimeout}`)
|
|
.action(runCommandAction(runRestartCommand));
|
|
|
|
program
|
|
.command('status')
|
|
.description('View service status')
|
|
.action(runCommandAction(runStatusCommand));
|
|
|
|
program
|
|
.command('help')
|
|
.description('Display help information')
|
|
.action(() => {
|
|
program.outputHelp();
|
|
});
|
|
|
|
program.parse(process.argv);
|
|
|
|
if (!process.argv.slice(2).length) {
|
|
program.outputHelp();
|
|
process.exitCode = 0;
|
|
}
|
|
}
|
|
|
|
main();
|