Skip to content

Commit

Permalink
Merge branch 'develop' - release 2.5.0
Browse files Browse the repository at this point in the history
  • Loading branch information
FabrizioSandri committed Nov 3, 2022
2 parents aa6109c + 0bea15e commit e200d35
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 64 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "r-integration",
"version": "2.4.0",
"version": "2.5.0",
"description": "Simple portable library used to interact with pre-installed R compiler by running commands or scripts(files)",
"main": "src/R.js",
"scripts": {
Expand Down
159 changes: 96 additions & 63 deletions src/R.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ var child_process = require("child_process");


/**
* get the current Operating System name
* Get the current Operating System name
*
* @returns {string} the operating system short name
* - "win" -> for Windows based Systems
Expand All @@ -28,22 +28,19 @@ getCurrentOs = () => {


/**
* execute a command in the OS shell (used to execute R command)
* Execute a command in the OS shell (used to execute R command)
*
* @param {string} command the command to execute
* @param {String[]} args an array of parameters to be passed to the command
* @returns {{string, string}} the command execution result
*/
executeShellCommand = (command) => {
executeShellCommand = (command, args) => {
let stdout;
let stderr;

try {
stdout = child_process.execSync(command, {
stdio: "pipe"
}).toString();
} catch (error) {
stderr = error;
}
let exec_res = child_process.spawnSync(command, args, { encoding : 'utf8' });
stdout = exec_res.stdout;
stderr = exec_res.stderr;

return {
stdout,
Expand All @@ -53,26 +50,45 @@ getCurrentOs = () => {


/**
* execute a command in the OS shell (used to execute R command) asynchronously
*
* Execute a command in the OS shell (used to execute R command) asynchronously
*
* @param {string} command the command to execute
* @returns {{string, string}} the command execution result
* @param {String[]} args an array of parameters to be passed to the command
* @returns {Promise<string>} the command execution result
*/
executeShellCommandAsync = (command) => {
executeShellCommandAsync = (command, args) => {
return new Promise((resolve, reject) => {
child_process.exec(command, (error, stdout, stderr) => {
if (error) {
reject(stderr);
var stdout = "";
var stderr = "";

let process = child_process.spawn(command, args, { encoding : 'utf8' });

process.stdout.on('data', (data) => {
data=data.toString();
stdout+=data;
});

process.stderr.on('data', (data) => {
data=data.toString();
stderr+=data;
});


process.on('exit', (code) => {
if (code !== 0) {
reject(command + " " + args.join(" ") + " exited with code " + code + " and error: " + stderr);
} else {
resolve(stdout);
}
resolve(stdout);
});

});
};

/**
* checks if Rscript(R) is installed od the system and returns
* the path where the binary is installed
*
* Check if Rscript(R) is installed od the system and returns the path where the
* binary is installed
*
* @param {string} path alternative path to use as binaries directory
* @returns {string} the path where the Rscript binary is installed, 0 otherwise
*/
Expand All @@ -98,8 +114,9 @@ isRscriptInstallaed = (path) => {
case "mac":
case "lin":
if (!path) {
// the command "which" is used to find the Rscript installation dir
path = executeShellCommand("which Rscript").stdout;
// the command "which" is used to find the Rscript installation
// directory
path = executeShellCommand("which", ["Rscript"]).stdout;
if (path) {
// Rscript is installed
installationDir = path.replace("\n", "");
Expand All @@ -122,18 +139,20 @@ isRscriptInstallaed = (path) => {

/**
* Execute in R a specific one line command
*
*
* @param {string} command the single line R command
* @param {string} RBinariesLocation optional parameter to specify an alternative location for the Rscript binary
* @returns {String[]} an array containing all the results from the command execution output, 0 if there was an error
* @param {string} RBinariesLocation optional parameter to specify an
* alternative location for the Rscript binary
* @returns {String[]} an array containing all the results from the command
* execution output, 0 if there was an error
*/
executeRCommand = (command, RBinariesLocation) => {
let RscriptBinaryPath = isRscriptInstallaed(RBinariesLocation);
let output = 0;

if (RscriptBinaryPath) {
var commandToExecute = `"${RscriptBinaryPath}" -e "${command}"`;
var commandResult = executeShellCommand(commandToExecute);
var args = ["-e", command];
var commandResult = executeShellCommand(RscriptBinaryPath, args);

if (commandResult.stdout) {
output = commandResult.stdout;
Expand All @@ -150,21 +169,22 @@ executeRCommand = (command, RBinariesLocation) => {
};

/**
* Execute in R a specific one line command - async
*
* Execute in R a specific one line command - asynchronously
*
* @param {string} command the single line R command
* @param {string} RBinariesLocation optional parameter to specify an alternative location for the Rscript binary
* @returns {String[]} an array containing all the results from the command execution output, null if there was an error
* @param {string} RBinariesLocation optional parameter to specify an
* alternative location for the Rscript binary
* @returns {Promise<string>} an array containing all the results from the command
* execution output, null if there was an error
*/
executeRCommandAsync = (command, RBinariesLocation) => {
return new Promise(function(resolve, reject) {

let RscriptBinaryPath = isRscriptInstallaed(RBinariesLocation);
let output = 0;

if (RscriptBinaryPath) {
var commandToExecute = `"${RscriptBinaryPath}" -e "${command}"`;
executeShellCommandAsync(commandToExecute).then((output) => {
var args = ["-e", command];
executeShellCommandAsync(RscriptBinaryPath, args).then((output) => {
output = filterMultiline(output);
resolve(output);
}).catch((stderr) => {
Expand All @@ -179,15 +199,20 @@ executeRCommandAsync = (command, RBinariesLocation) => {
};

/**
* execute in R all the commands in the file specified by the parameter fileLocation
* NOTE: the function reads only variables printed to stdout by the cat() or print() function.
* It is recommended to use the print() function insted of the cat() to avoid line break problem.
* If you use the cat() function remember to add the newline character "\n" at the end of each cat:
* for example cat(" ... \n")
*
* Execute in R all the commands in the file specified by the parameter
* fileLocation.
*
* NOTE: the function reads only variables printed to stdout by the cat() or
* print() function. It is recommended to use the print() function insted of the
* cat() to avoid line break problem. If you use the cat() function remember to
* add the newline character "\n" at the end of each cat: for example cat(" ...
* \n")
*
* @param {string} fileLocation where the file to execute is stored
* @param {string} RBinariesLocation optional parameter to specify an alternative location for the Rscript binary
* @returns {String[]} an array containing all the results from the command execution output, 0 if there was an error
* @param {string} RBinariesLocation optional parameter to specify an
* alternative location for the Rscript binary
* @returns {String[]} an array containing all the results from the command
* execution output, 0 if there was an error
*/
executeRScript = (fileLocation, RBinariesLocation) => {

Expand All @@ -200,8 +225,7 @@ executeRScript = (fileLocation, RBinariesLocation) => {
}

if (RscriptBinaryPath) {
var commandToExecute = `"${RscriptBinaryPath}" "${fileLocation}"`;
var commandResult = executeShellCommand(commandToExecute);
var commandResult = executeShellCommand(RscriptBinaryPath, [fileLocation]);

if (commandResult.stdout) {
output = commandResult.stdout;
Expand All @@ -219,7 +243,10 @@ executeRScript = (fileLocation, RBinariesLocation) => {
};

/**
* Formats the parameters so R could read them
* Formats the parameters so that R could read them
*
* @param {Object} params an array of parameters
* @returns {string} the parameters formatted in the proper way
*/
convertParamsArray = (params) => {
var methodSyntax = ``;
Expand All @@ -246,12 +273,15 @@ convertParamsArray = (params) => {


/**
* calls a R function located in an external script with parameters and returns the result
*
* Calls a R function located in an external script with parameters and returns
* the result
*
* @param {string} fileLocation where the file containing the function is stored
* @param {string} methodName the name of the method to execute
* @param {Object} params an object containing a binding between parameter names and value to pass to the function or an array
* @param {string} RBinariesLocation optional parameter to specify an alternative location for the Rscript binary
* @param {Object} params an object containing a binding between parameter names
* and value to pass to the function or an array
* @param {string} RBinariesLocation optional parameter to specify an
* alternative location for the Rscript binary
* @returns {string} the execution output of the function, 0 in case of error
*/
callMethod = (fileLocation, methodName, params, RBinariesLocation) => {
Expand Down Expand Up @@ -289,13 +319,14 @@ callMethod = (fileLocation, methodName, params, RBinariesLocation) => {
};

/**
* calls a R function with parameters and returns the result - async
*
* Calls a R function with parameters and returns the result - async
*
* @param {string} fileLocation where the file containing the function is stored
* @param {string} methodName the name of the method to execute
* @param {String []} params a list of parameters to pass to the function
* @param {string} RBinariesLocation optional parameter to specify an alternative location for the Rscript binary
* @returns {string} the execution output of the function
* @param {string} RBinariesLocation optional parameter to specify an
* alternative location for the Rscript binary
* @returns {Promise<string>} the execution output of the function
*/
callMethodAsync = (fileLocation, methodName, params, RBinariesLocation) => {
return new Promise(function(resolve, reject) {
Expand Down Expand Up @@ -337,11 +368,13 @@ callMethodAsync = (fileLocation, methodName, params, RBinariesLocation) => {


/**
* calls a standard R function with parameters and returns the result
*
* Calls a standard R function with parameters and returns the result
*
* @param {string} methodName the name of the method to execute
* @param {Object} params an object containing a binding between parameter names and value to pass to the function or an array
* @param {string} RBinariesLocation optional parameter to specify an alternative location for the Rscript binary
* @param {Object} params an object containing a binding between parameter names
* and value to pass to the function or an array
* @param {string} RBinariesLocation optional parameter to specify an
* alternative location for the Rscript binary
* @returns {string} the execution output of the function, 0 in case of error
*/
callStandardMethod = (methodName, params, RBinariesLocation) => {
Expand Down Expand Up @@ -380,17 +413,17 @@ callStandardMethod = (methodName, params, RBinariesLocation) => {


/**
* filters the multiline output from the executeRcommand and executeRScript functions
* using regular expressions
*
* Filters the multiline output from the executeRcommand and executeRScript
* functions using regular expressions
*
* @param {string} commandResult the multiline result of RScript execution
* @returns {String[]} an array containing all the results
*/
filterMultiline = (commandResult) => {
let data;

// remove last newline to avoid empty results
// NOTE: windows newline is composed by \r\n, GNU/Linux and Mac OS newline is \n
// remove last newline to avoid empty results NOTE: windows newline is
// composed by \r\n, GNU/Linux and Mac OS newline is \n
var currentOS = getCurrentOs();

commandResult = commandResult.replace(/\[\d+\] /g, "");
Expand Down

0 comments on commit e200d35

Please sign in to comment.