Source

services/dt/commands/with.js


const Command = require('./Command');
const { _err } = require('./utils');
const endCommand = 'endwith';
const startCommand = 'with';



/**
 * Allows for more complex logic by allowing you to control the output/input for commands
 * while keeping the commands readable
 *
 * basically sets whatever the result of the with operation into the source portion until it finds the endwith command
 *
 * Source object:
 *  - any
 *
 * @extends Command
 * @memberOf Commands
 */
class WithCommand extends Command {
    constructor(varStore, source) {
        super(varStore, source);
    }

    /**
     * @param {string[]|string} command the command split into words
     * @param {string[]} next the following Commands
     * @param {function(err, any)} [callback] for async versatility
     * @return {string|object} the command argument
     * @protected
     */
    _parseCommand(command, next, callback) {
        if (!next)
            throw new Error("No next defined");
        const commandsToConsider = [command];
        let cmd;
        let count = 0;
        while (!this._isEndCommand((cmd = next.shift())) && count === 0){
            let c = cmd.split(/\s+/);
            commandsToConsider.push(c);
            if (this._isStartCommand(c[0]))
                count++;
            if (this._isEndCommand(c[0]))
                count--;
        }

        commandsToConsider.push(cmd.split(/\s+/));
        callback(undefined, commandsToConsider);
    }

    _isStartCommand(cmd){
        return cmd.indexOf(startCommand) === 0;
    }

    _isEndCommand(cmd) {
        return cmd.indexOf(endCommand) === 0;
    }

    /**
     * @param {string[]} arg the command argument
     * @param {Archive} bar
     * @param {object} options
     * @param {function(err, Archive)} callback
     * @protected
     */
    _runCommand(arg, bar, options, callback) {
        let self = this;
        if (typeof options === 'function') {
            callback = options;
            options = undefined;
        }
        if (!callback){
            callback = bar;
            bar = undefined;
        }
        const _getByName = require('./Registry');

        const parseCommand = function(command, callback){
            const cmdName = command.shift();
            const actualCmd = _getByName(cmdName);
            if (!actualCmd)
                return callback(`Could not find command`);
            callback(undefined, cmdName, actualCmd, command);
        }

        const performWith = function(newSource, commands, callback){
            const cmd = commands.shift();
            if (!cmd)
                return callback(`No endWith command found. this should not be possible`);
            parseCommand(cmd, (err, cmdName, command, args) => {
                if (err)
                    return _err(`Could not parse the command ${cmd}`, err, callback);
                if (cmdName === endCommand)
                    return new command(self.varStore, self.source).execute(undefined, bar, callback);
                new command(self.varStore, self.source).execute(args, newSource, (err, result) => {
                    if (err)
                        return _err(`Could not execute command ${cmdName}`, err, callback);
                    console.log(`Command ${cmdName} executed with output ${JSON.stringify(result)}`);
                    performWith(newSource, commands, callback);
                });
            });
        }

        const cmdOrVar = arg[0][0];
        const cmd = _getByName(cmdOrVar);

        if (!cmd){
            console.log(`With VARIABLE executed: ${arg[0]}`);
            return performWith(arg.shift().shift(), arg, callback);
        }

        parseCommand(arg.shift(), (err, cmdName, command, args) => err
            ? _err(`Could not parse Command`, err, callback)
            : new (command)(self.varStore, self.source).execute(args, (err, result) => {
                if (err)
                    return _err(`Could not obtain result`, err, callback);
                console.log(`With COMMAND executed: ${JSON.stringify(result)}`);
                performWith(result, arg, callback);
            }));
    }
}

module.exports = WithCommand;