polyv-live-cli
Version:
CLI tool for managing PolyV live streaming services.
457 lines • 18.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.MonitorHandler = void 0;
const base_handler_1 = require("./base.handler");
const monitoring_dashboard_1 = require("../components/monitoring-dashboard");
const monitoring_1 = require("../config/monitoring");
const formatter_1 = require("../utils/formatter");
class MonitorHandler extends base_handler_1.BaseHandler {
constructor() {
super();
this.configManager = this.loadConfiguration();
}
loadConfiguration() {
try {
return monitoring_1.MonitoringConfigManager.fromEnvironment();
}
catch (envError) {
try {
return monitoring_1.MonitoringConfigManager.fromFile('./polyv-monitor.json');
}
catch (fileError) {
try {
const os = require('os');
const path = require('path');
const globalConfigPath = path.join(os.homedir(), '.polyv', 'monitor.json');
return monitoring_1.MonitoringConfigManager.fromFile(globalConfigPath);
}
catch (globalError) {
return new monitoring_1.MonitoringConfigManager();
}
}
}
}
async startMonitoring(options) {
try {
await this.checkTerminalCompatibility();
this.updateConfigFromOptions(options);
const validation = this.configManager.validateConfig();
if (!validation.valid) {
throw new Error(`Configuration validation failed:\n${validation.errors.join('\n')}`);
}
this.dashboard = new monitoring_dashboard_1.MonitoringDashboard(this.configManager.getConfig());
if (options.debug) {
this.enableDebugMode();
}
console.log('Starting PolyV Live Monitoring Dashboard...');
console.log(`Layout: ${this.configManager.getLayout()}`);
console.log(`Refresh interval: ${this.configManager.getRefreshInterval()}ms`);
console.log(`Theme: ${this.configManager.getTheme()}`);
console.log('Press ? or h for help, q or Ctrl+C to exit\n');
await this.dashboard.start();
}
catch (error) {
this.handleError(error instanceof Error ? error : new Error('Unknown error'));
}
}
async showStatus(options) {
try {
const status = {
isRunning: !!this.dashboard,
configuration: {
layout: this.configManager.getLayout(),
theme: this.configManager.getTheme(),
refreshInterval: this.configManager.getRefreshInterval(),
},
terminal: this.getTerminalInfo(),
performance: this.getPerformanceInfo(),
};
if (this.dashboard) {
const dashboardStatus = this.dashboard.getStatus();
Object.assign(status, {
dashboard: dashboardStatus,
});
}
if (options.output === 'json') {
console.log((0, formatter_1.formatJSON)(status));
}
else {
this.displayStatusTable(status);
}
}
catch (error) {
this.handleError(error instanceof Error ? error : new Error('Failed to get status'));
}
}
async showConfig(options) {
try {
const config = this.configManager.getConfig();
if (options.output === 'json') {
console.log((0, formatter_1.formatJSON)(config));
}
else {
this.displayConfigTable(config);
}
}
catch (error) {
this.handleError(error instanceof Error ? error : new Error('Failed to show config'));
}
}
async listLayouts(options) {
try {
const layouts = [
{
name: 'default',
description: 'Full-featured layout with all panels',
minSize: '120x30',
components: 4,
},
{
name: 'compact',
description: 'Compact layout for smaller terminals',
minSize: '80x24',
components: 2,
},
{
name: 'single',
description: 'Single panel layout for focused monitoring',
minSize: '60x20',
components: 1,
},
];
if (options.output === 'json') {
console.log((0, formatter_1.formatJSON)(layouts));
}
else {
const table = (0, formatter_1.formatTable)({
headers: ['Name', 'Description', 'Min Size', 'Components'],
data: layouts.map(layout => [
layout.name,
layout.description,
layout.minSize,
layout.components.toString(),
]),
});
console.log(table);
}
}
catch (error) {
this.handleError(error instanceof Error ? error : new Error('Failed to list layouts'));
}
}
async listThemes(options) {
try {
const themes = [
{
name: 'default',
description: 'Default light theme with blue accents',
colors: 'Blue/White/Black',
},
{
name: 'dark',
description: 'Dark theme with cyan accents',
colors: 'Cyan/White/Black',
},
];
if (options.output === 'json') {
console.log((0, formatter_1.formatJSON)(themes));
}
else {
const table = (0, formatter_1.formatTable)({
headers: ['Name', 'Description', 'Colors'],
data: themes.map(theme => [
theme.name,
theme.description,
theme.colors,
]),
});
console.log(table);
}
}
catch (error) {
this.handleError(error instanceof Error ? error : new Error('Failed to list themes'));
}
}
async testCompatibility(options) {
try {
const results = await this.runCompatibilityTests();
if (options.output === 'json') {
console.log((0, formatter_1.formatJSON)(results));
}
else {
this.displayCompatibilityResults(results);
}
}
catch (error) {
this.handleError(error instanceof Error ? error : new Error('Failed to test compatibility'));
}
}
async exportConfig(filepath) {
try {
this.configManager.saveToFile(filepath);
console.log(`Configuration exported to ${filepath}`);
}
catch (error) {
this.handleError(error instanceof Error ? error : new Error('Failed to export config'));
}
}
async importConfig(filepath) {
try {
this.configManager = monitoring_1.MonitoringConfigManager.fromFile(filepath);
const validation = this.configManager.validateConfig();
if (!validation.valid) {
throw new Error(`Invalid configuration:\n${validation.errors.join('\n')}`);
}
console.log(`Configuration imported from ${filepath}`);
}
catch (error) {
this.handleError(error instanceof Error ? error : new Error('Failed to import config'));
}
}
updateConfigFromOptions(options) {
const updates = {};
if (options.refresh) {
const refreshMs = parseInt(options.refresh) * 1000;
if (isNaN(refreshMs) || refreshMs < 1000) {
throw new Error('Refresh interval must be a number >= 1 second');
}
updates.refreshInterval = refreshMs;
}
if (options.layout) {
updates.layout = options.layout;
}
if (options.theme) {
updates.theme = options.theme;
}
if (options.config) {
try {
this.configManager = monitoring_1.MonitoringConfigManager.fromFile(options.config);
}
catch (error) {
throw new Error(`Failed to load config from ${options.config}: ${error}`);
}
}
if (Object.keys(updates).length > 0) {
this.configManager.updateConfig(updates);
}
}
async checkTerminalCompatibility() {
const terminalInfo = this.getTerminalInfo();
const terminalConfig = this.configManager.getTerminalConfig();
if (terminalInfo.width <= 1 || terminalInfo.height <= 1) {
throw new Error(`Terminal size could not be detected or is too small (${terminalInfo.width}x${terminalInfo.height}). ` +
`This usually happens in non-interactive environments. ` +
`Please run this command in a proper terminal with at least ${terminalConfig.minWidth}x${terminalConfig.minHeight} size.`);
}
if (terminalInfo.width < terminalConfig.minWidth ||
terminalInfo.height < terminalConfig.minHeight) {
throw new Error(`Terminal size too small. Required: ${terminalConfig.minWidth}x${terminalConfig.minHeight}, ` +
`Current: ${terminalInfo.width}x${terminalInfo.height}. ` +
`Please resize your terminal window or try using a smaller layout with --layout compact or --layout single.`);
}
try {
const blessed = require('blessed');
const testScreen = blessed.screen({
smartCSR: true,
title: 'Compatibility Test',
});
testScreen.destroy();
}
catch (error) {
throw new Error('Terminal is not compatible with blessed UI library');
}
}
getTerminalInfo() {
const envWidth = process.env['POLYV_TERMINAL_WIDTH'];
const envHeight = process.env['POLYV_TERMINAL_HEIGHT'];
let width = process.stdout.columns && process.stdout.columns > 0 ? process.stdout.columns : 120;
let height = process.stdout.rows && process.stdout.rows > 0 ? process.stdout.rows : 30;
if (envWidth && parseInt(envWidth) > 0) {
width = parseInt(envWidth);
}
if (envHeight && parseInt(envHeight) > 0) {
height = parseInt(envHeight);
}
return {
width,
height,
colorDepth: this.getColorDepth(),
platform: process.platform,
term: process.env['TERM'] || 'unknown',
};
}
getColorDepth() {
const colorterm = process.env['COLORTERM'];
const term = process.env['TERM'] || '';
if (colorterm === 'truecolor' || colorterm === '24bit') {
return 24;
}
else if (term.includes('256') || colorterm === '256') {
return 8;
}
else if (term.includes('color')) {
return 4;
}
return 1;
}
getPerformanceInfo() {
const memUsage = process.memoryUsage();
return {
memoryUsage: {
rss: Math.round(memUsage.rss / 1024 / 1024),
heapUsed: Math.round(memUsage.heapUsed / 1024 / 1024),
heapTotal: Math.round(memUsage.heapTotal / 1024 / 1024),
},
cpuUsage: process.cpuUsage(),
uptime: Math.round(process.uptime()),
};
}
enableDebugMode() {
process.env['POLYV_DEBUG'] = 'true';
console.log('Debug mode enabled');
}
displayStatusTable(status) {
console.log('PolyV Monitoring Dashboard Status\n');
const basicInfo = [
['Status', status.isRunning ? 'Running' : 'Stopped'],
['Layout', status.configuration.layout],
['Theme', status.configuration.theme],
['Refresh Interval', `${status.configuration.refreshInterval}ms`],
['Terminal Size', `${status.terminal.width}x${status.terminal.height}`],
['Color Depth', `${status.terminal.colorDepth}-bit`],
['Platform', status.terminal.platform],
];
if (status.dashboard) {
basicInfo.push(['Components', status.dashboard.components.toString()], ['Uptime', `${Math.round(status.dashboard.uptime / 1000)}s`]);
}
const table = (0, formatter_1.formatTable)({
headers: ['Property', 'Value'],
data: basicInfo,
});
console.log(table);
}
displayConfigTable(config) {
console.log('PolyV Monitoring Configuration\n');
const configInfo = [
['Refresh Interval', `${config.refreshInterval}ms`],
['Layout', config.layout],
['Theme', config.theme],
['Min Terminal Width', config.terminal.minWidth.toString()],
['Min Terminal Height', config.terminal.minHeight.toString()],
['Color Support', config.terminal.colorSupport ? 'Yes' : 'No'],
['Mouse Support', config.terminal.mouseSupport ? 'Yes' : 'No'],
['Unicode Support', config.terminal.unicodeSupport ? 'Yes' : 'No'],
['Max Memory', `${Math.round(config.performance.maxMemoryUsage / 1024 / 1024)}MB`],
['Max CPU', `${config.performance.maxCpuUsage}%`],
['Render Throttle', `${config.performance.renderThrottleMs}ms`],
['Components', config.components.length.toString()],
];
const table = (0, formatter_1.formatTable)({
headers: ['Setting', 'Value'],
data: configInfo,
});
console.log(table);
}
async runCompatibilityTests() {
const results = {
overall: 'pass',
tests: [],
};
const terminalInfo = this.getTerminalInfo();
const terminalConfig = this.configManager.getTerminalConfig();
if (terminalInfo.width >= terminalConfig.minWidth && terminalInfo.height >= terminalConfig.minHeight) {
results.tests.push({
name: 'Terminal Size',
status: 'pass',
message: `${terminalInfo.width}x${terminalInfo.height} (required: ${terminalConfig.minWidth}x${terminalConfig.minHeight})`,
});
}
else {
results.tests.push({
name: 'Terminal Size',
status: 'fail',
message: `${terminalInfo.width}x${terminalInfo.height} (required: ${terminalConfig.minWidth}x${terminalConfig.minHeight})`,
});
results.overall = 'fail';
}
if (terminalInfo.colorDepth >= 8) {
results.tests.push({
name: 'Color Support',
status: 'pass',
message: `${terminalInfo.colorDepth}-bit colors`,
});
}
else {
results.tests.push({
name: 'Color Support',
status: 'warn',
message: `${terminalInfo.colorDepth}-bit colors (8-bit recommended)`,
});
}
try {
const blessed = require('blessed');
const testScreen = blessed.screen({ smartCSR: true });
testScreen.destroy();
results.tests.push({
name: 'Blessed Compatibility',
status: 'pass',
message: 'Terminal is compatible with blessed library',
});
}
catch (error) {
results.tests.push({
name: 'Blessed Compatibility',
status: 'fail',
message: 'Terminal is not compatible with blessed library',
});
results.overall = 'fail';
}
const memUsage = process.memoryUsage();
const availableMemory = memUsage.rss / 1024 / 1024;
const requiredMemory = this.configManager.getPerformanceConfig().maxMemoryUsage / 1024 / 1024;
if (availableMemory < requiredMemory) {
results.tests.push({
name: 'Memory Availability',
status: 'pass',
message: `${Math.round(availableMemory)}MB used (${Math.round(requiredMemory)}MB limit)`,
});
}
else {
results.tests.push({
name: 'Memory Availability',
status: 'warn',
message: `${Math.round(availableMemory)}MB used (${Math.round(requiredMemory)}MB limit)`,
});
}
return results;
}
displayCompatibilityResults(results) {
console.log(`Compatibility Test Results: ${results.overall.toUpperCase()}\n`);
const table = (0, formatter_1.formatTable)({
headers: ['Test', 'Status', 'Details'],
data: results.tests.map((test) => [
test.name,
test.status.toUpperCase(),
test.message,
]),
});
console.log(table);
if (results.overall === 'fail') {
console.log('\nSome compatibility tests failed. The monitoring dashboard may not work properly.');
}
else if (results.tests.some((test) => test.status === 'warn')) {
console.log('\nSome tests have warnings. The monitoring dashboard should work but may have reduced functionality.');
}
else {
console.log('\nAll tests passed! The monitoring dashboard should work properly.');
}
}
handleError(error) {
if (this.dashboard) {
this.dashboard.stop();
}
this.displayError(error.message, error);
}
}
exports.MonitorHandler = MonitorHandler;
//# sourceMappingURL=monitor.handler.js.map