UNPKG

superjolt

Version:

AI-powered deployment platform with MCP support - Deploy JavaScript apps using natural language with Claude Desktop

172 lines 7.6 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.LogsCommand = void 0; const nest_commander_1 = require("nest-commander"); const authenticated_command_1 = require("./authenticated.command"); const api_service_1 = require("../services/api.service"); const common_1 = require("@nestjs/common"); const config_service_1 = require("../services/config.service"); const auth_service_1 = require("../services/auth.service"); const logger_service_1 = require("../services/logger.service"); const project_1 = require("../utils/project"); let LogsCommand = class LogsCommand extends authenticated_command_1.AuthenticatedCommand { apiService; configService; authService; logger; constructor(apiService, configService, authService, logger) { super(); this.apiService = apiService; this.configService = configService; this.authService = authService; this.logger = logger; } async execute(passedParams, options) { try { let serviceId = passedParams[0]; if (!serviceId) { const config = (0, project_1.readSuperjoltConfig)(); if (config?.serviceId) { serviceId = config.serviceId; this.logger.log(`Using service ID from .superjolt file: ${serviceId}`); } else { this.logger.error('Error: Service ID is required'); this.logger.log('Usage: superjolt logs [options] <serviceId>'); this.logger.log('\nNo .superjolt file found. Run "superjolt deploy" first or provide a service ID.'); process.exit(1); } } if (options.follow) { await this.followLogs(serviceId, options.tail || 20); } else { await this.getStaticLogs(serviceId, options.tail || 20); } } catch (error) { this.logger.error(`\n${error.message}`); process.exit(1); } } parseFollow() { return true; } parseTail(val) { const num = parseInt(val, 10); if (isNaN(num) || num < 1) { throw new Error('Tail value must be a positive number'); } return num; } async getStaticLogs(serviceId, tail) { this.logger.log(`Fetching last ${tail} lines for service: ${serviceId}...`); this.logger.log(''); const response = await this.apiService.getServiceLogs(serviceId, { tail }); this.logger.log(response.logs); if (response.metadata) { this.logger.log(''); this.logger.log('─'.repeat(80)); this.logger.log(`Lines: ${response.metadata.lines}${response.metadata.truncated ? ' (truncated)' : ''}`); } } async followLogs(serviceId, tail) { const { EventSource } = require('eventsource'); const chalkModule = require('chalk'); const chalk = chalkModule.default || chalkModule; this.logger.log(`Following logs for service: ${serviceId} (showing last ${tail} lines + new logs)...`); this.logger.log('Press Ctrl+C to stop following'); this.logger.log(''); const apiUrl = this.configService.getApiUrl(); const token = await this.authService.getToken(); const streamUrl = `${apiUrl}/service/${serviceId}/logs/stream?tail=${tail}&token=${encodeURIComponent(token || '')}`; const eventSource = new EventSource(streamUrl); return new Promise((resolve, reject) => { eventSource.onmessage = (event) => { try { const logEvent = JSON.parse(event.data); switch (logEvent.type) { case 'connected': this.logger.log(chalk.blue('📡 Connected to log stream')); this.logger.log(''); break; case 'log': if (logEvent.data) { process.stdout.write(logEvent.data); } break; case 'error': this.logger.error(chalk.red(`❌ Log stream error: ${logEvent.error}`)); eventSource.close(); reject(new Error(logEvent.error)); break; case 'end': this.logger.log(''); this.logger.log(chalk.yellow('📡 Log stream ended')); eventSource.close(); resolve(); break; default: this.logger.log(chalk.gray(`[${logEvent.type}] ${logEvent.message || JSON.stringify(logEvent)}`)); } } catch { this.logger.error('Failed to parse log event:', event.data); } }; eventSource.onerror = () => { this.logger.error(''); this.logger.error(chalk.red('❌ Connection to log stream failed')); eventSource.close(); reject(new Error('Log stream connection failed')); }; process.on('SIGINT', () => { this.logger.log(''); this.logger.log(chalk.yellow('📡 Stopping log stream...')); eventSource.close(); resolve(); }); }); } }; exports.LogsCommand = LogsCommand; __decorate([ (0, nest_commander_1.Option)({ flags: '-f, --follow', description: 'Follow log output (like tail -f)', }), __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", Boolean) ], LogsCommand.prototype, "parseFollow", null); __decorate([ (0, nest_commander_1.Option)({ flags: '-n, --tail <lines>', description: 'Number of lines to show from the end of the logs (default: 20)', }), __metadata("design:type", Function), __metadata("design:paramtypes", [String]), __metadata("design:returntype", Number) ], LogsCommand.prototype, "parseTail", null); exports.LogsCommand = LogsCommand = __decorate([ (0, common_1.Injectable)(), (0, nest_commander_1.Command)({ name: 'logs', arguments: '[serviceId]', description: 'Get logs for a service', }), __metadata("design:paramtypes", [api_service_1.ApiService, config_service_1.ConfigService, auth_service_1.AuthService, logger_service_1.LoggerService]) ], LogsCommand); //# sourceMappingURL=logs.command.js.map