cli/directives/ShellDirective.js

/**
 * @module flitter-cli/directives/ShellDirective
 */

const Directive = require('../Directive')
const nesh = require('nesh')
const color = require('colors/safe')

/**
 * Directive to launch an interactive Node prompt from within Flitter.
 * 
 * @extends module:flitter-cli/Directive~Directive
 */
class ShellDirective extends Directive {

    /**
     * Instantiate the class.
     */
    constructor(){
        super()

        /**
         * Options used by the shell. Includes custom welcome message and shell prompt.
         * 
         * @name ShellDirective#shell_options
         * @type {Object}
         */
        this.shell_options = {
            welcome: `powered by Flitter, © 2019 Garrett Mills
${color.magenta('The _flitter, _services, and _di globals have been created.')}`,
            prompt: `${color.blue('(')}flitter${color.blue(') ➤ ')}`,
        }
    }

    /**
     * Get the name of the directive. Used by ./flitter.
     * 
     * @static
     * @returns {string}
     */
    static name(){
        return "shell"
    }

    /**
     * Get the usage text for the directive. Used by ./flitter help.
     * 
     * @static
     * @returns {string}
     */
    static help(){
        return "launch an interactive shell"
    }

    /**
     * Handle an invocation of this directive. Launch an interactive shell.
     * @param {module:libflitter/app/FlitterApp~FlitterApp} app - the Flitter app
     * @param {Array} argv - the CLI arguments after the directive
     * @returns {Promise<void>}
     */
    async handle(app, argv){  
        await new Promise(
            (resolve, reject) => {
                // Create some global variables to allow access to Flitter
                global._flitter = app
                global._di = app.di()
                global._services = app.di().container.proxy()

                _di.container.register_singleton('target_directive', this.constructor)

                nesh.start(this.shell_options, (err, repl) => {
                    repl.on('exit', () => {
                        global._flitter = undefined
                        global._di = undefined
                        global._services = undefined
                        resolve()
                    })
                    this.repl = repl
                })
            }
        )
    }
    
}

module.exports = exports = ShellDirective