129 lines
4.7 KiB
TypeScript
129 lines
4.7 KiB
TypeScript
import * as plugins from '../../plugins.js';
|
|
import { tspmIpcClient } from '../../../client/tspm.ipcclient.js';
|
|
import type { CliArguments } from '../../types.js';
|
|
import { parseMemoryString, formatMemory } from '../../helpers/memory.js';
|
|
import { registerIpcCommand } from '../../registration/index.js';
|
|
|
|
export function registerAddCommand(smartcli: plugins.smartcli.Smartcli) {
|
|
registerIpcCommand(
|
|
smartcli,
|
|
'add',
|
|
async (argvArg: CliArguments) => {
|
|
const args = argvArg._.slice(1);
|
|
if (args.length === 0) {
|
|
console.error('Error: Please provide a command or .ts file');
|
|
console.log('Usage: tspm add <command|file.ts> [options]');
|
|
console.log('\nOptions:');
|
|
console.log(' --name <name> Optional name');
|
|
console.log(' --memory <size> Memory limit (e.g., 512MB, 2GB)');
|
|
console.log(' --cwd <path> Working directory');
|
|
console.log(' --watch Watch for file changes');
|
|
console.log(' --watch-paths <paths> Comma-separated paths');
|
|
console.log(' --autorestart Auto-restart on crash (default true)');
|
|
console.log(' -i, --interactive Enter interactive edit mode after adding');
|
|
return;
|
|
}
|
|
|
|
const script = args.join(' ');
|
|
const projectDir = argvArg.cwd || process.cwd();
|
|
const memoryLimit = argvArg.memory
|
|
? parseMemoryString(argvArg.memory)
|
|
: 512 * 1024 * 1024;
|
|
|
|
// Check for interactive flag
|
|
const isInteractive = argvArg.i || argvArg.interactive;
|
|
|
|
// Resolve .ts single-file execution via tsx if needed
|
|
const parts = script.split(' ');
|
|
const first = parts[0];
|
|
let command = script;
|
|
let cmdArgs: string[] | undefined;
|
|
if (parts.length === 1 && first.endsWith('.ts')) {
|
|
try {
|
|
const { createRequire } = await import('module');
|
|
const require = createRequire(import.meta.url);
|
|
const tsxPath = require.resolve('tsx/dist/cli.mjs');
|
|
const filePath = plugins.path.isAbsolute(first)
|
|
? first
|
|
: plugins.path.join(projectDir, first);
|
|
command = tsxPath;
|
|
cmdArgs = [filePath];
|
|
} catch {
|
|
command = 'tsx';
|
|
cmdArgs = [first];
|
|
}
|
|
}
|
|
|
|
const name = argvArg.name || script;
|
|
const watch = argvArg.watch || false;
|
|
const autorestart = argvArg.autorestart !== false;
|
|
const watchPaths = argvArg.watchPaths
|
|
? typeof argvArg.watchPaths === 'string'
|
|
? (argvArg.watchPaths as string).split(',')
|
|
: argvArg.watchPaths
|
|
: undefined;
|
|
|
|
console.log('Adding process configuration:');
|
|
console.log(` Command: ${script}${parts.length === 1 && first.endsWith('.ts') ? ' (via tsx)' : ''}`);
|
|
console.log(` Directory: ${projectDir}`);
|
|
console.log(` Memory limit: ${formatMemory(memoryLimit)}`);
|
|
console.log(` Auto-restart: ${autorestart}`);
|
|
if (watch) {
|
|
console.log(` Watch: enabled`);
|
|
if (watchPaths) console.log(` Watch paths: ${watchPaths.join(',')}`);
|
|
}
|
|
|
|
// Capture essential environment variables from the CLI environment
|
|
// so processes have access to the same environment they were added with
|
|
const essentialEnvVars: NodeJS.ProcessEnv = {
|
|
PATH: process.env.PATH || '',
|
|
HOME: process.env.HOME,
|
|
USER: process.env.USER,
|
|
SHELL: process.env.SHELL,
|
|
LANG: process.env.LANG,
|
|
LC_ALL: process.env.LC_ALL,
|
|
// Node.js specific
|
|
NODE_ENV: process.env.NODE_ENV,
|
|
NODE_PATH: process.env.NODE_PATH,
|
|
// npm/pnpm/yarn paths
|
|
npm_config_prefix: process.env.npm_config_prefix,
|
|
// Include any TSPM_ prefixed vars
|
|
...Object.fromEntries(
|
|
Object.entries(process.env).filter(([key]) => key.startsWith('TSPM_'))
|
|
),
|
|
};
|
|
|
|
// Remove undefined values
|
|
Object.keys(essentialEnvVars).forEach(key => {
|
|
if (essentialEnvVars[key] === undefined) {
|
|
delete essentialEnvVars[key];
|
|
}
|
|
});
|
|
|
|
const response = await tspmIpcClient.request('add', {
|
|
config: {
|
|
name,
|
|
command,
|
|
args: cmdArgs,
|
|
projectDir,
|
|
memoryLimitBytes: memoryLimit,
|
|
env: essentialEnvVars,
|
|
autorestart,
|
|
watch,
|
|
watchPaths,
|
|
},
|
|
});
|
|
|
|
console.log('✓ Added');
|
|
console.log(` Assigned ID: ${response.id}`);
|
|
|
|
// If interactive flag is set, enter edit mode
|
|
if (isInteractive) {
|
|
const { interactiveEditProcess } = await import('../../helpers/interactive-edit.js');
|
|
await interactiveEditProcess(response.id);
|
|
}
|
|
},
|
|
{ actionLabel: 'add process config' },
|
|
);
|
|
}
|