UNPKG

replicas-cli

Version:

CLI for managing Replicas workspaces - SSH into cloud dev environments with automatic port forwarding

128 lines 6.45 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.prepareWorkspaceConnection = prepareWorkspaceConnection; const chalk_1 = __importDefault(require("chalk")); const prompts_1 = __importDefault(require("prompts")); const path_1 = __importDefault(require("path")); const fs_1 = __importDefault(require("fs")); const config_1 = require("./config"); const api_1 = require("./api"); const ssh_1 = require("./ssh"); const git_1 = require("./git"); const replicas_config_1 = require("./replicas-config"); const ports_1 = require("./ports"); async function prepareWorkspaceConnection(workspaceName, options) { const orgId = (0, config_1.getOrganizationId)(); if (!orgId) { throw new Error('No organization selected. Please run "replicas org switch" first.'); } // Step 1: Query workspaces by name console.log(chalk_1.default.blue(`\nSearching for workspace: ${workspaceName}...`)); const response = await (0, api_1.orgAuthenticatedFetch)(`/v1/workspaces?name=${encodeURIComponent(workspaceName)}`); if (response.workspaces.length === 0) { throw new Error(`No workspaces found with name matching "${workspaceName}".`); } // Step 2: If multiple workspaces, prompt user to select one let selectedWorkspace; if (response.workspaces.length === 1) { selectedWorkspace = response.workspaces[0]; } else { console.log(chalk_1.default.yellow(`\nFound ${response.workspaces.length} workspaces matching "${workspaceName}":`)); const selectResponse = await (0, prompts_1.default)({ type: 'select', name: 'workspaceId', message: 'Select a workspace:', choices: response.workspaces.map(ws => ({ title: `${ws.name} (${ws.status || 'unknown'})`, value: ws.id, description: `IP: ${ws.ipv4_address || 'N/A'} | Instance: ${ws.instance_type || 'N/A'}`, })), }); if (!selectResponse.workspaceId) { throw new Error('Workspace selection cancelled.'); } selectedWorkspace = response.workspaces.find(ws => ws.id === selectResponse.workspaceId); } console.log(chalk_1.default.green(`\n✓ Selected workspace: ${selectedWorkspace.name}`)); console.log(chalk_1.default.gray(` IP: ${selectedWorkspace.ipv4_address}`)); console.log(chalk_1.default.gray(` Status: ${selectedWorkspace.status || 'unknown'}`)); if (!selectedWorkspace.ipv4_address) { throw new Error('Workspace does not have an IP address. It may not be running yet.'); } // Step 3: Get SSH key console.log(chalk_1.default.blue('\nRetrieving SSH key...')); const privateKey = await (0, ssh_1.getSSHKey)(selectedWorkspace.ssh_key_id); // Write key to a temporary file for SSH const keyPath = path_1.default.join(config_1.CONFIG_DIR, 'keys', `${selectedWorkspace.ssh_key_id}.pem`); fs_1.default.writeFileSync(keyPath, privateKey, { mode: 0o600 }); console.log(chalk_1.default.green('✓ SSH key ready')); // Step 4: Handle --copy flag let repoName = null; if (options.copy) { if (!(0, git_1.isInsideGitRepo)()) { console.log(chalk_1.default.yellow('\nWarning: Not inside a git repository. Skipping file copy.')); } else { repoName = (0, git_1.getGitRepoName)(); const replicasConfig = (0, replicas_config_1.readReplicasConfig)(); if (!replicasConfig || !replicasConfig.copy || replicasConfig.copy.length === 0) { console.log(chalk_1.default.yellow('\nNo files to copy (replicas.json not found or empty).')); } else { console.log(chalk_1.default.blue(`\nCopying files to workspace (repo: ${repoName})...`)); const { valid, invalid } = (0, replicas_config_1.validateCopyFiles)(replicasConfig.copy); if (invalid.length > 0) { console.log(chalk_1.default.yellow(`\nWarning: ${invalid.length} file(s) not found locally:`)); invalid.forEach(file => console.log(chalk_1.default.gray(` - ${file}`))); } for (const file of valid) { const localPath = (0, replicas_config_1.getAbsoluteCopyPath)(file); const remotePath = `/home/ubuntu/workspaces/${repoName}/${file}`; console.log(chalk_1.default.gray(` Copying ${file}...`)); try { await (0, ssh_1.scpCopyFile)(keyPath, localPath, remotePath, selectedWorkspace.ipv4_address); console.log(chalk_1.default.green(` ✓ ${file}`)); } catch (error) { console.log(chalk_1.default.red(` ✗ Failed to copy ${file}: ${error instanceof Error ? error.message : 'Unknown error'}`)); } } console.log(chalk_1.default.green(`\n✓ File copy complete (${valid.length} files)`)); } } } if (!repoName && (0, git_1.isInsideGitRepo)()) { try { repoName = (0, git_1.getGitRepoName)(); } catch { // Ignore errors, repo name is optional } } // Step 6: Handle port forwarding const portMappings = new Map(); // Add ports from replicas.json if inside a git repo console.log(chalk_1.default.blue('\nSetting up port forwarding...')); if ((0, git_1.isInsideGitRepo)()) { const replicasConfig = (0, replicas_config_1.readReplicasConfig)(); if (replicasConfig && replicasConfig.ports && replicasConfig.ports.length > 0) { const mappings = await (0, ports_1.mapPortsToLocal)(replicasConfig.ports); for (const [remotePort, localPort] of mappings) { portMappings.set(remotePort, localPort); console.log(chalk_1.default.gray(` Forwarding localhost:${localPort} -> workspace:${remotePort}`)); } } } console.log(chalk_1.default.green('✓ Port forwarding configured')); return { workspace: selectedWorkspace, sshKeyPath: keyPath, portMappings, repoName, }; } //# sourceMappingURL=workspace-connection.js.map