UNPKG

@re-shell/cli

Version:

Full-stack development platform uniting microservices and microfrontends. Build complete applications with .NET (ASP.NET Core Web API, Minimal API), Java (Spring Boot, Quarkus, Micronaut, Vert.x), Rust (Actix-Web, Warp, Rocket, Axum), Python (FastAPI, Dja

313 lines (312 loc) • 12.3 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.launchTUI = launchTUI; const child_process_1 = require("child_process"); const path = __importStar(require("path")); const fs = __importStar(require("fs-extra")); const chalk_1 = __importDefault(require("chalk")); const spinner_1 = require("../utils/spinner"); class IPCBridge { constructor(process) { this.messageHandlers = new Map(); this.responseHandlers = new Map(); this.process = process; this.setupMessageHandling(); } setupMessageHandling() { if (this.process.stdout) { this.process.stdout.on('data', (data) => { const lines = data.toString().split('\n').filter((line) => line.trim()); for (const line of lines) { try { const message = JSON.parse(line); this.handleMessage(message); } catch (e) { // Not a JSON message, probably debug output if (process.env.DEBUG) { console.log('TUI:', line); } } } }); } if (this.process.stderr) { this.process.stderr.on('data', (data) => { if (process.env.DEBUG) { console.error('TUI Error:', data.toString()); } }); } } async handleMessage(message) { if (message.type === 'response') { const handler = this.responseHandlers.get(message.id); if (handler) { handler(message.data); this.responseHandlers.delete(message.id); } return; } const handler = this.messageHandlers.get(message.type); if (handler) { try { const result = await handler(message.data); this.send('response', result, message.id); } catch (error) { this.send('error', { message: error instanceof Error ? error.message : 'Unknown error' }, message.id); } } } on(type, handler) { this.messageHandlers.set(type, handler); } send(type, data, id) { const message = { type, id: id || Math.random().toString(36).substring(7), data }; if (this.process.stdin) { this.process.stdin.write(JSON.stringify(message) + '\n'); } } async request(type, data) { return new Promise((resolve, reject) => { const id = Math.random().toString(36).substring(7); this.responseHandlers.set(id, (responseData) => { resolve(responseData); }); setTimeout(() => { this.responseHandlers.delete(id); reject(new Error('Request timeout')); }, 30000); this.send(type, data, id); }); } } async function launchTUI(options) { const spinner = (0, spinner_1.createSpinner)('Initializing TUI interface...'); try { // Check if Go is installed await checkGoInstallation(); // Ensure TUI directory exists const tuiDir = path.join(__dirname, '../tui'); await fs.ensureDir(tuiDir); // Check if TUI binary exists or needs building await ensureTUIBinary(tuiDir); spinner.succeed('TUI ready'); // Launch the TUI process console.log(chalk_1.default.cyan('\nšŸš€ Launching Re-Shell TUI...\n')); const tuiProcess = (0, child_process_1.spawn)('go', ['run', '.'], { cwd: tuiDir, stdio: ['pipe', 'pipe', 'inherit'], env: { ...process.env, RESHELL_PROJECT_PATH: options.project || process.cwd(), RESHELL_TUI_MODE: options.mode || 'dashboard', RESHELL_DEBUG: options.debug ? 'true' : 'false' } }); // Set up IPC bridge const ipc = new IPCBridge(tuiProcess); // Register command handlers setupIPCHandlers(ipc, options); // Wait for process to exit await new Promise((resolve, reject) => { tuiProcess.on('exit', (code) => { if (code === 0) { resolve(); } else { reject(new Error(`TUI process exited with code ${code}`)); } }); tuiProcess.on('error', (error) => { reject(error); }); }); } catch (error) { spinner.fail('Failed to launch TUI'); console.error(chalk_1.default.red('Error:', error instanceof Error ? error.message : 'Unknown error')); process.exit(1); } } async function checkGoInstallation() { return new Promise((resolve, reject) => { const goProcess = (0, child_process_1.spawn)('go', ['version'], { stdio: 'ignore' }); goProcess.on('exit', (code) => { if (code === 0) { resolve(); } else { reject(new Error('Go is not installed. Please install Go from https://golang.org/dl/')); } }); goProcess.on('error', () => { reject(new Error('Go is not installed. Please install Go from https://golang.org/dl/')); }); }); } async function ensureTUIBinary(tuiDir) { const mainGoPath = path.join(tuiDir, 'main.go'); if (!await fs.pathExists(mainGoPath)) { throw new Error('TUI source code not found. Please ensure the TUI module is properly installed.'); } // Check if go.mod exists const goModPath = path.join(tuiDir, 'go.mod'); if (!await fs.pathExists(goModPath)) { // Initialize Go module const initProcess = (0, child_process_1.spawn)('go', ['mod', 'init', 'reshell-tui'], { cwd: tuiDir, stdio: 'ignore' }); await new Promise((resolve, reject) => { initProcess.on('exit', (code) => { if (code === 0) resolve(); else reject(new Error('Failed to initialize Go module')); }); }); // Install dependencies const tidyProcess = (0, child_process_1.spawn)('go', ['mod', 'tidy'], { cwd: tuiDir, stdio: 'ignore' }); await new Promise((resolve, reject) => { tidyProcess.on('exit', (code) => { if (code === 0) resolve(); else reject(new Error('Failed to install Go dependencies')); }); }); } } function setupIPCHandlers(ipc, options) { // Handle project information requests ipc.on('get-project-info', async (data) => { const projectPath = data.path || options.project || process.cwd(); const packageJsonPath = path.join(projectPath, 'package.json'); try { const packageJson = await fs.readJson(packageJsonPath); return { name: packageJson.name || path.basename(projectPath), version: packageJson.version || '0.0.0', description: packageJson.description || '', path: projectPath, type: 're-shell' // TODO: Detect project type }; } catch (error) { return { name: path.basename(projectPath), version: '0.0.0', description: 'Re-Shell Project', path: projectPath, type: 'unknown' }; } }); // Handle file system operations ipc.on('list-directory', async (data) => { try { const entries = await fs.readdir(data.path); const result = []; for (const entry of entries) { const entryPath = path.join(data.path, entry); const stats = await fs.stat(entryPath); result.push({ name: entry, path: entryPath, isDirectory: stats.isDirectory(), size: stats.size, modified: stats.mtime }); } return result; } catch (error) { throw new Error(`Failed to list directory: ${error instanceof Error ? error.message : 'Unknown error'}`); } }); // Handle CLI command execution ipc.on('execute-command', async (data) => { const { command, args } = data; // Import the appropriate command handler try { switch (command) { case 'init': const { initMonorepo } = await Promise.resolve().then(() => __importStar(require('./init'))); return await initMonorepo(args.name || 'new-project', args); case 'add': const { addMicrofrontend } = await Promise.resolve().then(() => __importStar(require('./add'))); return await addMicrofrontend(args.name || 'new-app', args); case 'list': const { listMicrofrontends } = await Promise.resolve().then(() => __importStar(require('./list'))); return await listMicrofrontends(args); case 'build': const { buildMicrofrontend } = await Promise.resolve().then(() => __importStar(require('./build'))); return await buildMicrofrontend(args); case 'serve': const { serveMicrofrontend } = await Promise.resolve().then(() => __importStar(require('./serve'))); return await serveMicrofrontend(args); default: throw new Error(`Unknown command: ${command}`); } } catch (error) { throw new Error(`Command execution failed: ${error instanceof Error ? error.message : 'Unknown error'}`); } }); // Handle configuration operations ipc.on('get-config', async (data) => { const { getMergedConfig } = await Promise.resolve().then(() => __importStar(require('../utils/config'))); return await getMergedConfig(data.projectPath); }); ipc.on('set-config', async (data) => { const { ConfigManager } = await Promise.resolve().then(() => __importStar(require('../utils/config'))); const configManager = new ConfigManager(); await configManager.updateGlobalConfig({ [data.key]: data.value }); return { success: true }; }); }