alwaysai
Version:
The alwaysAI command-line interface (CLI)
164 lines (149 loc) • 5.13 kB
text/typescript
import * as logSymbols from 'log-symbols';
import { CliTerseError, CliUsageError } from '@alwaysai/alwayscli';
import { checkProcessorBrand } from './destination-prompt-component';
import { targetPathPromptComponent } from './target-path-prompt-component';
import { targetProtocolPromptComponent } from './target-protocol-prompt-component';
import { writeTargetJsonFileComponent } from './write-target-json-file-component';
import {
DOCKER_IMAGE_ID_INITIAL_VALUE,
ALWAYSAI_CLI_EXECUTABLE_NAME
} from '../../../constants';
import {
deviceCheckAndUpdateComponent,
deviceSelectComponent,
getTargetHostnameComponent
} from '../../device';
import { checkForDockerComponent } from '../../docker';
import { RequiredWithYesMessage, echo, logger } from '../../../util';
import {
getTargetHardwareType,
parseTargetHW,
TargetHardware,
TargetJsonFile,
TargetPathDefaultValue,
TargetProtocol
} from '../../../core/app';
import { addDeviceToProject, ProjectJsonFile } from '../../../core/project';
import { findOrWritePrivateKeyFileComponent } from '../../general';
import { ALWAYSAI_TARGET_HW_OVERRIDE } from '../../../environment';
export async function targetJsonComponent(props: {
yes: boolean;
targetProtocol?: TargetProtocol;
targetHardware?: TargetHardware;
targetHostname?: string;
targetPath?: string;
deviceId?: string;
}) {
const { yes } = props;
const currentTargetJson = TargetJsonFile();
const currentTargetProtocol = currentTargetJson.readTargetProtocolSafe();
let targetProtocol;
if (yes) {
targetProtocol = props.targetProtocol ?? currentTargetProtocol;
if (!targetProtocol) {
throw new CliUsageError(RequiredWithYesMessage('protocol'));
}
if (targetProtocol === 'native:' || targetProtocol === 'docker:') {
if (!(await checkProcessorBrand())) {
throw new CliUsageError(
'edgeIQ is not supported on devices with Atom/Celeron processors.'
);
}
}
} else if (!props.targetProtocol) {
targetProtocol = await targetProtocolPromptComponent({
prevTargetProtocol: currentTargetProtocol
});
} else {
targetProtocol = props.targetProtocol;
}
switch (targetProtocol) {
case 'native:': {
await writeTargetJsonFileComponent({
targetProtocol
});
break;
}
case 'docker:': {
await checkForDockerComponent();
// Order of precedence: Command line > environment variable >
// auto-determine based on system
const targetHardware =
props.targetHardware ??
parseTargetHW(ALWAYSAI_TARGET_HW_OVERRIDE) ??
(await getTargetHardwareType({}));
echo(`${logSymbols.success} Set target hardware to ${targetHardware}`);
await writeTargetJsonFileComponent({
targetProtocol,
dockerImageId: DOCKER_IMAGE_ID_INITIAL_VALUE,
targetHardware
});
break;
}
case 'ssh+docker:': {
await findOrWritePrivateKeyFileComponent({ yes });
const projectJsonFile = ProjectJsonFile();
const projectConfig = projectJsonFile.read().project;
if (!projectConfig) {
throw new CliTerseError(
`App must have a project associated with it. Run '${ALWAYSAI_CLI_EXECUTABLE_NAME} app configure' to select a project.`
);
}
const projectId = projectConfig.id;
const deviceSelectOut = await deviceSelectComponent({
yes,
deviceId: props.deviceId
});
const device = deviceSelectOut.device;
const isNewDevice = deviceSelectOut.new;
const targetHostname = await getTargetHostnameComponent({
yes,
device,
targetHostname: props.targetHostname
});
if (targetHostname === undefined) {
throw new CliTerseError(
'Cannot access selected device! The device hostname is unknown.'
);
}
await deviceCheckAndUpdateComponent({
yes,
targetHostname,
device,
isNewDevice
});
await addDeviceToProject({ device, projectId });
await checkForDockerComponent({ targetHostname });
let targetPath =
props.targetPath ??
currentTargetJson.readFieldSafe({ name: 'targetPath' }) ??
TargetPathDefaultValue();
if (!yes) {
targetPath = await targetPathPromptComponent({
targetHostname,
targetPath
});
}
if (parseTargetHW(ALWAYSAI_TARGET_HW_OVERRIDE) !== undefined) {
const msg = 'ALWAYSAI_TARGET_HW set but not used for remote device';
echo(`${logSymbols.warning} ${msg}`);
logger.warn(msg);
}
const targetHardware =
props.targetHardware ??
(await getTargetHardwareType({ targetHostname }));
echo(`${logSymbols.success} Set target hardware to ${targetHardware}`);
TargetJsonFile().write({
targetProtocol,
targetHostname,
targetPath,
dockerImageId: DOCKER_IMAGE_ID_INITIAL_VALUE,
targetHardware,
deviceId: device.uuid
});
break;
}
default:
throw new Error('Unsupported protocol');
}
}