alwaysai
Version:
The alwaysAI command-line interface (CLI)
133 lines (121 loc) • 3.79 kB
text/typescript
import { CliTerseError } from '@alwaysai/alwayscli';
import { existsSync } from 'fs';
import { ALWAYSAI_CLI_EXECUTABLE_NAME } from '../../constants';
import { checkUserIsLoggedInComponent } from '../user';
import { JsSpawner } from '../../util';
import { appCheckComponent } from './app-check-component';
import { AppJsonFile, TargetJsonFile } from '../../core/app';
import { ALWAYSAI_OS_PLATFORM } from '../../environment';
import {
APP_JSON_FILE_NAME,
VENV_BIN_ACTIVATE,
VENV_SCRIPTS_ACTIVATE
} from '../../paths';
const BASH_INITIAL_ARGS = ['-o', 'onecmd', '-O', 'huponexit', '-c'];
export async function appStartComponent(
props: {
noSuperuser?: boolean;
volumes?: string[];
env_vars?: string[];
args?: string[];
} = {}
) {
const { noSuperuser, volumes, env_vars, args = [] } = props;
await checkUserIsLoggedInComponent({ yes: true });
await appCheckComponent();
const appJson = AppJsonFile().read();
const startScript = appJson.scripts?.start;
if (!startScript) {
throw new CliTerseError(
`This application does not define a "start" script in its application configuration file "${APP_JSON_FILE_NAME}"`
);
}
const targetJsonFile = TargetJsonFile();
const targetJson = targetJsonFile.read();
let exitCode: number | void;
const quotedArgsString = args.map((arg) => `'${arg}'`).join(' ');
const tty = process.stdin.isTTY;
switch (targetJson.targetProtocol) {
case 'docker:': {
const spawner = targetJsonFile.readContainerSpawner({
volumes,
env_vars
});
exitCode = await spawner.runForeground({
exe: '/bin/bash',
args: [
...BASH_INITIAL_ARGS,
`. ${VENV_BIN_ACTIVATE} && ${startScript} ${quotedArgsString}`
],
cwd: '.',
tty,
expose5000: true,
superuser: !noSuperuser
});
break;
}
// This case differs from "docker:"" only in the extra single quotes around the command
case 'ssh+docker:': {
const spawner = targetJsonFile.readContainerSpawner({
volumes,
env_vars
});
exitCode = await spawner.runForeground({
exe: '/bin/bash',
args: [
...BASH_INITIAL_ARGS,
`'. ${VENV_BIN_ACTIVATE} && ${startScript} ${quotedArgsString}'`
],
cwd: '.',
tty,
expose5000: true,
superuser: !noSuperuser
});
break;
}
case 'native:': {
switch (ALWAYSAI_OS_PLATFORM) {
case 'win32': {
if (!existsSync(VENV_SCRIPTS_ACTIVATE)) {
throw new CliTerseError(
`File not found "${VENV_SCRIPTS_ACTIVATE}". Did you run "${ALWAYSAI_CLI_EXECUTABLE_NAME} app install"?`
);
}
exitCode = await JsSpawner().runForeground({
exe: 'cmd.exe',
args: [
'/c',
`${VENV_SCRIPTS_ACTIVATE} && ${startScript} ${args.join(' ')}`
]
});
break;
}
case 'darwin': {
if (!existsSync(VENV_BIN_ACTIVATE)) {
throw new CliTerseError(
`File not found "${VENV_BIN_ACTIVATE}". Did you run "${ALWAYSAI_CLI_EXECUTABLE_NAME} app install"?`
);
}
exitCode = await JsSpawner().runForeground({
exe: '/bin/sh',
args: [
`-c`,
`. ${VENV_BIN_ACTIVATE} && ${startScript} ${quotedArgsString}`
]
});
break;
}
default: {
throw new CliTerseError(
`OS ${ALWAYSAI_OS_PLATFORM} not supported for native start`
);
}
}
break;
}
default: {
throw new Error('Unsupported protocol');
}
}
return exitCode || 0;
}