Source: core/commandFactory.js

/**
 * @class CommandFactory
 * @classdesc This class has one static method that returns a new instance
 * of a command.
 * @author ruckola
 */
class CommandFactory {

    /**
     * @method
     * @static
     * @param {String} action - The name of the command to return. If no action
     * is given, it returns the {@link Macro} command.
     * @param {string} commandDir - The directory in which the command can be found.
     * Normally this directory should be specified in the module configuration.<br>
     * If namespaces are used, they must be included.
     * @description Searches the commands directory for a file with a
     * filename that equals the value of the 'action' parameter. If it is found
     * it tries to create a new instance of the command and returns it.<br>
     * If the the 'action' parameter has value "macro", then the build-in {@link Macro} command
     * is returned.<br><br>
     * <strong>Warning! - Command filepaths must not contain whitespaces!<br></strong>
     */
    static getCommand(action = 'macro', commandDir) {
       
        if (action == 'macro') {
            var cmdClass = require('../commands/macro.js');
            var cmd = new cmdClass;
            return cmd;
        }

        var fs = require('fs');
        var helper = require('./helper');
        const path = require('path');
        var appRootDir = require('app-root-dir').get();
        
       
        if (!(typeof action === 'string')) { //check if action is of type string.
            throw new TypeError("Parameter 'action' is of the wrong type. It should be of type 'string'.")
        } else if(!(typeof commandDir === 'string')) { //check if commandDir is of type string.
            throw new TypeError("Parameter 'commandDir' is of the wrong type. It should be of type 'string'.")
        };

        
        //DANGEROUS! 
        //you can't rely on directory names above the application root. Needs to be fixed.
        
        var re = /\s/;
        if (action.match(re)) { //check for whitespaces in 'action'
            throw new Error("Illegal character found in 'action'-parameter.");
        }else if (commandDir.match(re)){ //check for whitespaces in 'commandDir'
            throw new Error("Illegal character found in 'commandDir'-parameter.");
        }
        
        
        //build command file-path from 'action'
        var className = action;
        var filePath = path.normalize(commandDir + "/" + className + ".js");
        var absolutePath = path.resolve(__dirname, filePath);

        //check if file exists
        if (!fs.existsSync(absolutePath)) {
            throw new Error("The file '" + filePath + "' doesn't exist.");
        }

        //require the file
        //instantiate the class
        //throw an error if the required class doesn't exists
        try {
            var cmdClass = require(filePath);
            var cmd = new cmdClass;
        } catch (err) {
            console.log("The class %s in file '%s' couldn't be instantiated. Error: %s", helper.ucfirst(className), filePath, err);
        }
        //write custom properties for testing purposes.
        cmd.props = {
            action: action,
            className: className,
            filePath: filePath,
            absolutePath: absolutePath
        };
        //return the command object
        return cmd;

    }
}

module.exports = CommandFactory;