alwaysai
Version:
The alwaysAI command-line interface (CLI)
223 lines • 8.02 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.projectSelectComponent = void 0;
const logSymbols = require("log-symbols");
const chalk = require("chalk");
const path_1 = require("path");
const alwayscli_1 = require("@alwaysai/alwayscli");
const fs_extra_1 = require("fs-extra");
const tempy = require("tempy");
const constants_1 = require("../../constants");
const util_1 = require("../../util");
const general_1 = require("../general");
const project_1 = require("../../core/project");
const infrastructure_1 = require("../../infrastructure");
const stringify_error_1 = require("../../util/stringify-error");
const BASE_URL = 'https://github.com/alwaysai/';
const ARCHIVE_PATH = 'archive/refs/heads/main.tar.gz';
const STARTER_APPS = [
{
webName: 'realtime_object_detector',
purpose: 'Object Detection',
downloadUrl: `${BASE_URL}object-detector/${ARCHIVE_PATH}`
},
{
webName: 'detector_tracker',
purpose: 'Object Detection with Tracking',
downloadUrl: `${BASE_URL}detector-tracker/${ARCHIVE_PATH}`
},
{
webName: 'image_classifier',
purpose: 'Image Classification',
downloadUrl: `${BASE_URL}image-classifier/${ARCHIVE_PATH}`
},
{
webName: 'semantic_segmentation_voc',
purpose: 'Semantic Segmentation',
downloadUrl: `${BASE_URL}semantic-segmentation-voc/${ARCHIVE_PATH}`
},
{
webName: 'realtime_pose_estimator',
purpose: 'Human Pose Estimation',
downloadUrl: `${BASE_URL}pose-estimator/${ARCHIVE_PATH}`
},
{
webName: 'hello_world_face_detector',
purpose: 'Face Detector',
downloadUrl: `${BASE_URL}face-detector/${ARCHIVE_PATH}`
},
{
webName: 'instance_segmentation',
purpose: 'Instance Segmentation',
downloadUrl: `${BASE_URL}instance-segmentation/${ARCHIVE_PATH}`
}
];
async function projectSelectComponent(props) {
const { yes, projectUuid } = props;
if (yes && !projectUuid) {
throw new alwayscli_1.CliUsageError((0, util_1.RequiredWithYesMessage)('project'));
}
const project = projectUuid
? await (0, project_1.getProjectByUUID)(projectUuid)
: await selectFromListOfProjects();
if (project.starter_app) {
let appName = project.starter_app;
// Replace legacy "hello_world" starter app with face detector on outdated projects
if (appName === 'hello_world') {
appName = 'hello_world_face_detector';
}
await downloadStarterApp({ yes, appName });
}
return project;
}
exports.projectSelectComponent = projectSelectComponent;
async function selectFromListOfProjects() {
const authInfo = await (0, infrastructure_1.CliAuthenticationClient)().getInfo();
const projects = await (0, infrastructure_1.CliRpcClient)().listProjectsUserIsCollaborator({
user_name: authInfo.username
});
const choices = [
{ title: chalk.green.bold('Create new project'), value: 'new' }
];
projects.forEach((project, index) => {
choices.push({
title: project.name,
value: `${index}`
});
});
const choice = await (0, util_1.promptForInput)({
purpose: 'to select a project',
questions: [
{
type: 'select',
name: 'project',
message: 'Select a project or create a new project',
initial: 0,
choices
}
]
});
if (choice.project === 'new') {
return await createProject();
}
return projects[choice.project];
}
async function createProject() {
const { username } = await (0, infrastructure_1.CliAuthenticationClient)().getInfo();
const team = await (0, infrastructure_1.CliRpcClient)().listTeamsUserIsOwner({
user_name: username
});
// TODO: Need to limit input characters to match dashboard implementation
const input = await (0, util_1.promptForInput)({
purpose: 'to choose a project name',
questions: [
{
type: 'text',
name: 'name',
message: 'Enter a project name:'
}
]
});
const name = input.name;
const choice = await (0, util_1.promptForInput)({
purpose: 'to select a project type',
questions: [
{
type: 'select',
name: 'type',
message: 'How would you like to initialize your project?',
initial: 0,
choices: [
{ title: 'From a Starter App', value: 'starterApp' },
{ title: 'As an empty app', value: 'empty' }
]
}
]
});
let starterApp = '';
switch (choice.type) {
case 'starterApp': {
const choices = [];
STARTER_APPS.forEach((app) => {
choices.push({
title: app.purpose,
value: app.webName
});
});
const choice = await (0, util_1.promptForInput)({
purpose: 'to select a starter app',
questions: [
{
type: 'select',
name: 'app',
message: 'Select a Starter App',
initial: 0,
choices
}
]
});
starterApp = choice.app;
break;
}
case 'empty':
default:
// Do nothing
}
const project = await (0, infrastructure_1.CliRpcClient)().createProject({
owner: username,
team_id: team[0].id,
name,
description: '',
git_url: '',
starter_app: starterApp
});
return project;
}
async function checkDirIsEmpty(dir) {
const fileNames = (0, fs_extra_1.readdirSync)(dir);
return fileNames.length === 0;
}
async function downloadStarterApp(props) {
const { yes, appName } = props;
let url = undefined;
if ((await checkDirIsEmpty(process.cwd())) === false) {
const proceed = yes ||
(await (0, general_1.confirmPromptComponent)({
message: 'Would you like to download the Starter App? Files in this directory may be overwritten!'
}));
if (!proceed) {
(0, util_1.echo)('Skipping download of starter app!');
return;
}
}
for (const app of STARTER_APPS) {
if (app.webName === appName) {
url = app.downloadUrl;
break;
}
}
if (url === undefined) {
throw new alwayscli_1.CliTerseError(`Starter App "${appName}" not found!`);
}
const tmpDir = tempy.directory();
try {
const fileStream = await (0, util_1.fetchFilestream)(url);
const spawner = (0, util_1.JsSpawner)({ path: tmpDir });
await spawner.untar(fileStream);
}
catch (e) {
util_1.logger.error((0, stringify_error_1.stringifyError)(e));
throw new alwayscli_1.CliTerseError(`Failed to download "${url}", check your internet connection and retry`);
}
const fileNames = (0, fs_extra_1.readdirSync)(tmpDir);
if (fileNames.length !== 1 || !fileNames[0]) {
util_1.logger.error(`Expected application to contain a single directory: ${fileNames}`);
throw new alwayscli_1.CliTerseError(`Expected application to contain a single directory. ${constants_1.PLEASE_REPORT_THIS_ERROR_MESSAGE}`);
}
const srcSpawner = (0, util_1.JsSpawner)({ path: (0, path_1.join)(tmpDir, fileNames[0]) });
const destSpawner = (0, util_1.JsSpawner)({ path: process.cwd() });
await (0, util_1.copyFiles)(srcSpawner, destSpawner);
await srcSpawner.rimraf();
(0, util_1.echo)(`${logSymbols.success} Download Starter App`);
}
//# sourceMappingURL=project-select-component.js.map