UNPKG

brainwise-demo-cli

Version:

brainwise-Newcli is an open source chatbot platform based on Rasa.

208 lines (183 loc) 7.62 kB
import open from 'open' import ora from 'ora'; import yaml from 'js-yaml'; import fs from 'fs-extra'; import path from 'path'; import { Docker } from 'docker-cli-js'; import boxen from 'boxen'; import inquirer from 'inquirer'; import shell from 'shelljs'; import chalk from 'chalk'; import { initCommand } from './commands/init'; import { dockerComposeUp, dockerComposeDown, dockerComposeFollow, dockerComposeStop, dockerComposeStart, dockerComposeRestart, stopRunningProjects, getRunningDockerResources, watchFolder, } from './commands/services'; import { wait, isProjectDir, verifySystem, getbrainwiseVersion, failSpinner, stopSpinner, getContainerAndImageNames, succeedSpinner, consoleError, } from './utils'; const program = require('commander'); const version = getbrainwiseVersion(); function collect(value, previous) { return previous.concat([value]); } program .version(version) .description('brainwise--demo-cli CLI') .action(() => console.log(`\n${chalk.red.bold('ERROR:')} Unsupported command. Run ${chalk.cyan.bold('brainwise-demo-cli --help')} for more information.\n`)); program .command('init') .option('--path <path>', 'Desired project path') .option('--img-brainwise <image:tag>', 'Image for the Brainwise service') .option('--img-brainwise-api <image:tag>', 'Image used by the Brainwise--api service') .option('--img-rasa <image:tag>', 'Image used by the Rasa service') .option('--ci', 'No spinners, no prompt confirmations') .description('Create a new brainwise chatbot project.') .action(initCommand); program .command('up') .option('-e, --exclude <service>', 'Do not run a given service', collect, []) .option('-v, --verbose', 'Display Docker Compose start-up logs') .option('--ci', 'No spinners, no prompt confirmations') .description('Start a brainwise chatbot project. Must be executed in your project\'s directory') .action(dockerComposeUp); program .command('down') .option('-v, --verbose', 'Display Docker Compose start-up logs') .description('Stops a brainwise chatbot project and releases Docker resources. Must be executed in your project\'s directory') .action(dockerComposeDown); program .command('logs') .option('--ci', 'Print out logs once and do not hook to TTY') .description('Display brainwise chatbot logs. Must be executed in your project\'s directory') .action(dockerComposeFollow); program .command('killall') .option('--remove-images', 'Will also remove Brainwise-cli related Docker images') .description('Stops any running brainwise chatbot project') .action(killAllCommand); program .command('stop <service>') .description('Stop a brainwise chatbot service (interactive). Must be executed in your project\'s directory') .action(dockerComposeStop); program .command('start <service>') .description('Start a brainwise chatbot service (interactive). Must be executed in your project\'s directory') .action(dockerComposeStart); program .command('restart <service>') .description('Restart a brainwise chatbot service (interactive). Must be executed in your project\'s directory') .action(dockerComposeRestart); program .command('watch') .description('Restart the Actions service automatically on file change. Must be executed in your project\'s directory') .action(watchFolder); program .command('docs') .description('Open the online documentation in your browser') .action(openDocs); async function openDocs() { const spinner = ora() spinner.start(`Opening ${chalk.green.bold('https://brainwise.me')} in your browser...`) await wait(2000); await open('https://brainwise.me') spinner.succeed('Done') console.log('\n'); } async function killAllCommand(cmd) { const { stop } = await inquirer.prompt({ type: 'confirm', name: 'stop', message: 'This will stop any running brainwise chatbot project and cleanup remaining Docker resources. This will not affect your project\'s data. Proceed ?', default: true, }); if (stop){ const spinner = ora(); try { await stopRunningProjects( 'Attempting to stop a running project...', `A project was stopped and all its resources released. Your data is safe and you can always restart it by running ${chalk.cyan.bold( 'brainwise-demo-cli up', )} from your project\'s folder.\n`, 'All clear 👍.', spinner, ); cleanupDocker({rm: true, rmi: cmd.removeImages}, spinner) stopSpinner(spinner) } catch (e) { failSpinner(spinner, e); } } } async function general() { const choices = []; try { await verifySystem() const { containers } = await getRunningDockerResources() if (isProjectDir()){ if (containers && containers.length){ choices.push({ title: 'Stop brainwise-demo-cli', cmd: () => dockerComposeDown({ verbose: false }) }); choices.push({ title: 'Show logs', cmd: dockerComposeFollow }); } else { choices.push({ title: 'Start project', cmd: () => dockerComposeUp({ verbose: false })}); } } else { if (containers && containers.length){ choices.push({ title: 'Stop brainwise-demo-cli', cmd: () => killAllCommand({ verbose: false }) }); } choices.push({ title: 'Create a new project', cmd: initCommand }); } choices.push({ title: 'Browse the online documentation', cmd: openDocs}); choices.push({ title: 'More options (display the --help)', cmd: () => shell.exec('Brainwise-cli -h') }); choices.push({ title: 'Exit', cmd: () => process.exit(0) }); console.log(boxen(`Welcome to ${chalk.green.bold('brainwise-demo-cli')}!\nversion: ${getbrainwiseVersion()}`, { padding: 1, margin: 1 })); const { action } = await inquirer.prompt({ type: 'list', name: 'action', message: 'What do you want to do?', choices: choices.map(choice => choice.title), }); choices.find(c => c.title === action).cmd() } catch (e) { console.log(e) } } async function cleanupDocker({rm, rmi}, spinner = ora()) { const composePath = path.resolve(__dirname, '..', 'project-template', '.Brainwise-cli', 'docker-compose-template.yml'); const { services } = yaml.safeLoad(fs.readFileSync(composePath), 'utf-8'); const containersAndImageNames = getContainerAndImageNames(null, services); if (rm) runDockerPromises('rm', containersAndImageNames, spinner); if (rmi) runDockerPromises('rmi', containersAndImageNames, spinner); } async function runDockerPromises(cmd, { containers, images }, spinner) { const docker = new Docker({}); const name = cmd === 'rm' ? 'containers' : 'images'; const array = cmd === 'rm' ? containers : images; const promises = array.map(i => docker.command(`${cmd} ${i}`).catch(()=>{})); try { await Promise.all(promises); return succeedSpinner(spinner, `Docker ${name} removed.`); } catch (e) { consoleError(e); failSpinner(spinner, `Could not remove Docker ${name}.`); } finally { stopSpinner(); } } const commandr = program.parse(process.argv); if (commandr.rawArgs.length == 2) general();