@xec-sh/cli
Version:
Xec: The Universal Shell for TypeScript
224 lines • 7.24 kB
JavaScript
import chalk from 'chalk';
import { $ } from '@xec-sh/core';
import * as clack from '@clack/prompts';
import { parseTimeout } from './time.js';
import { ConfigurationManager } from '../config/configuration-manager.js';
export async function executeDirectCommand(args, options = {}) {
const command = args.join(' ');
if (!command.trim()) {
throw new Error('No command specified');
}
const firstArg = args[0];
if (!firstArg) {
await executeLocally(command, options);
return;
}
const target = await detectTarget(firstArg);
if (target) {
await executeOnTarget(target, args.slice(1).join(' '), options);
}
else {
await executeLocally(command, options);
}
}
async function detectTarget(arg) {
const configManager = new ConfigurationManager();
const config = await configManager.load();
const targets = config.targets || {};
const hosts = targets.hosts || {};
if (hosts[arg]) {
return {
type: 'ssh',
name: arg,
config: { ...hosts[arg], type: 'ssh' },
};
}
const containers = targets.containers || {};
if (containers[arg]) {
return {
type: 'docker',
name: arg,
config: { ...containers[arg], type: 'docker' },
};
}
const pods = targets.pods || {};
if (pods[arg]) {
return {
type: 'kubernetes',
name: arg,
config: { ...pods[arg], type: 'k8s' },
};
}
try {
const dockerResult = await $.local() `docker ps --format "{{.Names}}" | grep -E "^${arg}$"`.quiet().nothrow();
if (dockerResult.ok && dockerResult.stdout.trim()) {
return { type: 'docker', name: arg };
}
}
catch {
}
try {
const k8sResult = await $.local() `kubectl get pod ${arg} -o name`.quiet().nothrow();
if (k8sResult.ok && k8sResult.stdout.trim()) {
return { type: 'kubernetes', name: arg };
}
}
catch {
}
return null;
}
async function executeOnTarget(target, command, options) {
if (!command.trim()) {
throw new Error('No command specified for target');
}
const targetDisplay = chalk.cyan(target.name);
if (!options.quiet) {
clack.log.info(`Executing on ${targetDisplay} (${target.type})...`);
}
let engine;
switch (target.type) {
case 'ssh':
{
const sshConfig = target.config || { host: target.name };
engine = $.ssh({
host: sshConfig.host || target.name,
username: sshConfig.username || sshConfig.user || process.env['USER'] || 'root',
port: sshConfig.port || 22,
privateKey: sshConfig.privateKey || sshConfig.key || sshConfig.identityFile,
password: sshConfig.password,
passphrase: sshConfig.passphrase,
});
break;
}
case 'docker':
{
const containerName = target.config?.name || target.name;
engine = $.docker({ container: containerName });
break;
}
case 'kubernetes':
{
const podConfig = target.config || {};
engine = $.k8s({
pod: podConfig.name || target.name,
namespace: podConfig.namespace || 'default',
container: podConfig.container,
});
break;
}
}
if (options.cwd) {
engine = engine.cd(options.cwd);
}
if (options.env) {
engine = engine.env(options.env);
}
if (options.timeout) {
const timeoutMs = parseTimeout(options.timeout);
engine = engine.timeout(timeoutMs);
}
const result = await engine.raw `${command}`;
if (result.stdout && !options.quiet) {
console.log(result.stdout.trim());
}
if (result.stderr && options.verbose) {
console.error(chalk.yellow(result.stderr.trim()));
}
}
async function executeLocally(command, options) {
let engine = $.local();
if (options.cwd) {
engine = engine.cd(options.cwd);
}
if (options.env) {
engine = engine.env(options.env);
}
if (options.timeout) {
const timeoutMs = parseTimeout(options.timeout);
engine = engine.timeout(timeoutMs);
}
const result = await engine.raw `${command}`;
if (result.stdout && !options.quiet) {
console.log(result.stdout.trim());
}
if (result.stderr && options.verbose) {
console.error(chalk.yellow(result.stderr.trim()));
}
}
export function isDirectCommand(args, commandRegistry, taskNames) {
if (args.length === 0) {
return false;
}
const firstArg = args[0];
if (!firstArg) {
return false;
}
if (firstArg.startsWith('-')) {
return false;
}
if (taskNames && taskNames.includes(firstArg)) {
return false;
}
if (commandRegistry) {
if (commandRegistry.includes(firstArg)) {
return false;
}
}
else {
const knownSubcommands = [
'exec', 'ssh', 'docker', 'k8s', 'run', 'init', 'config',
'env', 'copy', 'list', 'new', 'version', 'watch',
'on', 'in', 'help', 'cache', 'forward', 'interactive', 'logs',
'release', 'r', 'i', 'v',
'tasks', 'explain'
];
if (knownSubcommands.includes(firstArg)) {
return false;
}
}
if (firstArg && (firstArg.includes(' ') || (firstArg.startsWith('"') && firstArg.endsWith('"')))) {
return true;
}
return true;
}
export async function createTargetEngine(target, options = {}) {
const config = target.config;
switch (target.type) {
case 'local':
return $;
case 'ssh':
return $.ssh({
host: config.host,
username: config.user || config.username,
port: config.port,
privateKey: config.privateKey,
password: config.password,
passphrase: config.passphrase,
keepAlive: config.keepAlive,
keepAliveInterval: config.keepAliveInterval,
...options
});
case 'docker':
return $.docker({
container: config.container || target.name,
image: config.image || 'alpine:latest',
user: config.user,
workingDir: config.workdir,
tty: config.tty,
...options
});
case 'k8s':
case 'kubernetes':
return $.k8s({
pod: config.pod || target.name,
namespace: config.namespace || 'default',
container: config.container,
context: config.context,
kubeconfig: config.kubeconfig,
...options
});
default:
throw new Error(`Unsupported target type: ${target.type}`);
}
}
//# sourceMappingURL=direct-execution.js.map