UNPKG

alwaysai

Version:

The alwaysAI command-line interface (CLI)

223 lines 8.02 kB
"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