How to iterate a loop in nodejs - node.js

I have a json variable
var a = { Account: [ 'Name', 'Site', 'BillingState', 'Phone', 'Type', 'Owner.Alias' ],
Contact: [ 'Name1', 'Site1' ] }
and i am iterating loop like this
app.post('/', function (req, res) {
a = req.body.table_structure
b = createSelectQuery(a) res.send(b) // this return only "FROM CONTACT" })
Where i have created another function hoping i could in return get the desired string but the loop went async
function createSelectQuery(a){
var selectQuery = "Select "
var obj = JSON.parse(a);
for (var c in obj){
for (var d in obj[c]){
selectQuery += obj[c][d] + ', '
}
selectQuery = "FROM "+c
}
return selectQuery
}
I am expecting result "SELECT Name, .. etc from Account but getting
only FROM Account as output

Try this
function createSelectQuery(a){
var selectQuery = "Select ";
var obj = JSON.parse(a);
for (var c in obj) {
selectQuery += obj[c].join(", ") + " FROM " + c;
}
return selectQuery;
}

you need to use callback which will make your looping synchronous

I belive because in JSON file 'Account' is array and you try to loop in to it as if it was an object. Try :
function createSelectQuery(a){
var selectQuery = "Select "
var obj = JSON.parse(a);
for (var c in obj){
for (var d=0; d < obj[c].length; d++){
selectQuery += obj[c][d] + ', '
}
selectQuery = "FROM "+c
}
return selectQuery
}

Instead of loop, you can try join the string using arr.join() and then append the string with Object.keys. That will do the trick
var selectQuery = "Select ";
var a = { Account: [ 'Name', 'Site', 'BillingState', 'Phone', 'Type', 'Owner.Alias' ]};
var obj = a;
var arr = obj['Account'];
var joinStr = arr.join(',').toString();
selectQuery = selectQuery +" "+joinStr +" FROM "+Object.keys(a);
console.log(selectQuery);

Related

Edit a JSON object

I retrieved a JSON object from a local database, I want to edit a value (invItems) and add a new value to it (filed[filed.invItems]), then upload it back to the database, but it does not seem to work (the JSON does not seem to change)
async function invPut(itemID, message) {
var filed = await frenzyDB.getKey(id + "_invcache");
console.log("Before: " + filed)
newInvItems = filed.invItems + 1;
filed.invItems = newInvItems;
filed[filed.invItems] = itemID;
console.log("After: " + filed);
await frenzyDB.addKey(id + "_invcache", filed)
}
Console Output:
Before: {"invItems":0}
After: {"invItems":0}
It shows no errors, but the JSON doesnt change. Am I doing something wrong? If so, what can I do to fix it?
Thanks for all your help!
Notes:
frenzyDB is just a javascript file that deals with a standard REPL.it Database
Code of frenzyDB:
const Database = require("#replit/database")
const db = new Database()
async function addKey(key, value) {
await db.set(key, value).then(() => {return;});
}
async function getKey(key) {
return await db.get(key).then(value => {return value;});
}
function listAllKeys() {
db.list().then(keys => {return keys;});
}
async function hasKey(key) {
var keys = await listAllKeys();
if (keys.includes(key)) {
return true;
} else {
return false;
}
}
async function removeKey(key) {
await db.delete(key).then(() => {return;});
}
module.exports = {
addKey,
getKey,
listAllKeys,
hasKey,
removeKey
};
Edit: Latest code:
async function invPut(itemID, message) {
await init(message.author.id);
var filed = await frenzyDB.getKey(message.author.id + "_invcache");
console.log(filed)
const result = {};
result.invItems = (filed['invItems'] + 1) || 1;
result.hasOwnProperty(filed.invItems) ? result[filed.invItems + 1] = itemID : result[filed.invItems] = itemID;
console.log(result);
frenzyDB.addKey(message.author.id + "_invcache", result)
message.reply("A **"+ itemIDs[itemID].name + "** was placed in your inventory");
return true;
}
EDIT 2: Latest Console Output:
{ '4': 3, invItems: 5 }
{ '5': 3, invItems: 6 }
Any help will be appreciated!
Thanks
Try this
// Demo Data
const itemID = 10;
var filed = { "invItems" : 0 };
// Real function
console.log("Before: " + JSON.stringify(filed));
const result = {};
result.invItems = (filed['invItems'] + 1) || 1;
result.hasOwnProperty(filed.invItems) ? result[filed.invItems + 1] = itemID : result[filed.invItems] = itemID;
console.log("After: " + JSON.stringify(result));
The result I get is
Before: {"invItems":0}
After: {"0":10,"invItems":1}
You would then of course use result to store the data away in the DB.
async function invPut(itemID, message) {
// Typo?
var filed = await frenzyDB.getKey(itemID + "_invcache");
console.log("Before: " + filed)
const result = {};
result.invItems = (filed['invItems'] + 1) || 1;
result.hasOwnProperty(filed.invItems) ? result[filed.invItems + 1] = itemID : result[filed.invItems] = itemID;
console.log("After: " + result);
// Typo?
await frenzyDB.addKey(itemID + "_invcache", result)
}
Answer Edit:
const result = { ...filed };
result.invItems = (filed['invItems'] + 1) || 1;
result.hasOwnProperty(filed.invItems) ? result[filed.invItems + 1] = itemID : result[filed.invItems] = itemID;
console.log(JSON.stringify(result));
maybe this will help you
const json = fs.readFileSync(`${__dirname}/data/data.json`, "utf-8");
const inputData = JSON.parse(json);
inputData.push({input: 'front'}) // creates new element for data.json
-------------------------------------------
array.push({front: 'front', back: 'back'});

Update Existing Line Item Values in Netsuite SuiteScript 2.0

No matter what I do, I can't update the line item values in an inbound shipment record. I have a ton of debug statements, and I know that I technically am at the correct line, but when I try to get or set values, they are empty.
I am working in dynamic mode, and so in order to loop, I found something online that said I needed to stringify the record. I see all the correct data, but any time I try to manipulate the values, it doesn't do anything, or the values are empty. I also keep getting asked to provide the required fields, but for this particular line, they are already there.
Here is my code:
function doPost(restletBody){
log.debug('Called from POST', restletBody);
var success = [],
errors = [];
restletBody.data.forEach(function(e)
{
try
{
//Inbound Shipment Stuff
var ibsID = e.ibShipments.inboundShipmentRecordID;
var containerNumber = e.ibShipments.containerNumber;
var memo = e.ibShipments.memo;
var cargoReturnDate = e.ibShipments.cargoReturnDate;
var billoflading = e.ibShipments.billoflading;
var quantityexpected = e.ibShipments.quantityexpected;
var destCountry = e.ibShipments.destCountry;
var actualdeliverydate = e.ibShipments.actualdeliverydate;
var expecteddeliverydate = e.ibShipments.expecteddeliverydate;
var poDueDate = e.ibShipments.poDueDate;
var shipmentstatus = e.ibShipments.shipmentstatus;
var factory = e.ibShipments.factory;
var vesselNumber = e.ibShipments.vesselNumber;
var actualshippingdate = e.ibShipments.actualshippingdate;
var expectedshippingdate = e.ibShipments.expectedshippingdate;
var vesselBookingNumber = e.ibShipments.vesselBookingNumber;
var bookingDate = e.ibShipments.bookingDate;
var recID = null;
if((ibsID == "" || ibsID == null) && (containerNumber != "" || memo != "" || cargoReturnDate != "" ||
billoflading != "" || quantityexpected != "" || destCountry != "" || actualdeliverydate != "" ||
expecteddeliverydate != "" || poDueDate != "" || shipmentstatus != "" || factory != "" || vesselNumber != "" ||
actualshippingdate != "" || expectedshippingdate != "" || vesselBookingNumber != "" || bookingDate != ""))
{
//Create a new record
log.debug('Create Record', "");
var rec =
r.create({
type: "inboundshipment",
isDynamic: true,
defaultValues: null
});
//Might need to save the record, then add the fields
recID = rec.save();
var i = 1;
}
else
{
log.debug('Update Record Instead', ibsID);
recID = ibsID;
}
var inboundShipmentUpdate = r.load({
type: 'inboundshipment',
id: recID,
isDynamic: true
});
//Get Values from purchase order
var poID = e.poID;
var poName = e.poName;
var poShipDate = e.poShipDate;
var poShipWindowStart = e.poShipWindowStart;
if(poShipWindowStart != "")
poShipWindowStart = new Date(poShipWindowStart);
else
poShipWindowStart = "";
var poShipWindowEnd = e.poShipWindowEnd;
if(poShipWindowEnd != "")
poShipWindowEnd = new Date(poShipWindowEnd);
else
poShipWindowEnd = "";
//Item Fields
var itemID = e.items.itemID;
var itemDisplayName = e.items.displayName;
var itemName = e.items.name;
//Get Values from inbound shipment entry
var shipmentnumber = e.ibShipments.shipmentnumber;
var bookingDate = e.ibShipments.bookingDate;
if(bookingDate != "")
bookingDate = new Date(bookingDate);
else
bookingDate = "";
var vesselBookingNumber = e.ibShipments.vesselBookingNumber;
var expectedshippingdate = e.ibShipments.expectedshippingdate;
if(expectedshippingdate != "")
expectedshippingdate = new Date(expectedshippingdate);
else
expectedshippingdate = "";
var actualshippingdate = e.ibShipments.actualshippingdate;
if(actualshippingdate != "")
actualshippingdate = new Date(actualshippingdate);
else
actualshippingdate = "";
var vesselNumber = e.ibShipments.vesselNumber;
var containerNumber = e.ibShipments.containerNumber;
var factory = e.ibShipments.factory;
var shipmentStatus = e.ibShipments.shipmentstatus;
var poDueDate = e.ibShipments.poDueDate;
var expecteddeliverydate = e.ibShipments.expecteddeliverydate;
if(expecteddeliverydate != "")
expecteddeliverydate = new Date(expecteddeliverydate);
else
expecteddeliverydate = "";
var actualdeliverydate = e.ibShipments.actualdeliverydate;
if(actualdeliverydate != "")
actualdeliverydate = new Date(actualdeliverydate);
else
actualdeliverydate = "";
var destCountry = e.ibShipments.destCountry;
var quantityexpected = e.ibShipments.quantityexpected;
var quantityreceived = e.ibShipments.quantityreceived;
var billoflading = e.ibShipments.billoflading;
var cargoReturnDate = e.ibShipments.cargoReturnDate;
if(cargoReturnDate != "")
cargoReturnDate = new Date(cargoReturnDate);
else
cargoReturnDate = "";
var memo = e.ibShipments.memo;
//Set Field Values
inboundShipmentUpdate.setValue('actualshippingdate', actualshippingdate);
inboundShipmentUpdate.setValue('actualdeliverydate',actualdeliverydate);
inboundShipmentUpdate.setValue('custrecord_kk_booking_date', bookingDate);
inboundShipmentUpdate.setValue('custrecord_kk_cargo_return_dt',cargoReturnDate);
inboundShipmentUpdate.setValue('expectedshippingdate',expectedshippingdate);
inboundShipmentUpdate.setValue('expecteddeliverydate',expecteddeliverydate);
inboundShipmentUpdate.setValue('shipmentmemo', memo);
inboundShipmentUpdate.setValue('externaldocumentnumber',containerNumber);
//inboundShipmentUpdate.setValue('shipmentstatus',shipmentStatus);
inboundShipmentUpdate.setValue('billoflading',billoflading);
inboundShipmentUpdate.setValue('custrecord_kk_vesselbooking_number',vesselBookingNumber);
inboundShipmentUpdate.setValue('vesselnumber',vesselNumber);
inboundShipmentUpdate.setValue('custrecord_kk_destination',destCountry);
log.debug("Inside Line Items", e.items.itemID + " " + poID);
//The item must be unique, so it cannot already be on the inbound shipment. Do not set the current sublist value to the item
//if it already exists
var objCurRecIBS = JSON.parse(JSON.stringify(inboundShipmentUpdate));
log.debug("objCurRecIBS", objCurRecIBS );
var objSublistsIBS = objCurRecIBS.sublists ? objCurRecIBS.sublists : '';
log.debug("objSublistsIBS", objSublistsIBS );
var objIBSItems = objSublistsIBS.items ? objSublistsIBS.items : '';
log.debug("objIBSItems", objIBSItems );
var itemLineCountIBS = Object.keys(objSublistsIBS.items).length; //First Item is an empty item
var itemPresent = false;
//First Item is an empty item, so start at 1
for (var k = 1; k < itemLineCountIBS; k++)
{
//This keeps coming back empty
var currentQuantity = inboundShipmentUpdate.getCurrentSublistValue({
sublistId: "items",
fieldId: "quantityexpected"
});
log.debug("Current Quantity", currentQuantity + "Line " + k );
//So does this
var currentItem = inboundShipmentUpdate.getCurrentSublistValue({
sublistId: "items",
fieldId: "shipmentitem"
});
log.debug("Current Item", currentItem + "Line " + k );
var currItemIDIBS = objIBSItems[Object.keys(objSublistsIBS.items)[k]].itemid;
log.debug("Current Line Item Id", currItemIDIBS);
var currentLineIBS = objIBSItems[Object.keys(objSublistsIBS.items)[k]];
log.debug("cURRENT iTEM IBS Line", currentLineIBS);
if(currItemIDIBS == itemID)
{
//Update the existing line, since it is already present
itemPresent = true;
log.debug("Current Item Exists in the IBS", itemPresent);
//This is empty, too
var linePO = inboundShipmentUpdate.getCurrentSublistValue({
sublistId: "items",
fieldId: "purchaseorder"
});
log.debug("Line PO: ", linePO);
var currentQuantity = inboundShipmentUpdate.getCurrentSublistValue({
sublistId: "items",
fieldId: "quantityexpected"
});
log.debug("Current Quantity", currentQuantity + "Line " + k );
var newQuantity = currentQuantity + 2;
log.debug("New Quantity", newQuantity );
inboundShipmentUpdate.selectLine({
sublistId: 'items',
line: k
});
inboundShipmentUpdate.setCurrentSublistValue({
sublistId: "items",
fieldId: "quantityexpected",
value: newQuantity
//quantityexpected
});
inboundShipmentUpdate.commitLine({sublistId:"items"});
log.debug("Inside SELECT Line Items", "Line Committed" );
}
}
if(!itemPresent)
{
log.debug("Inside Item Present Check", itemPresent);
inboundShipmentUpdate.setCurrentSublistValue({
sublistId: "items",
fieldId: "shipmentitem",
value: shipmentitem
});
inboundShipmentUpdate.setCurrentSublistValue({
sublistId: "items",
fieldId: "quantityexpected",
value: quantityexpected
});
log.debug("Inside Line Items", "Shipment ITEM Added " + shipmentitem );
inboundShipmentUpdate.commitLine({sublistId:"items"});
log.debug("Inside Line Items", "Line Committed" );
}
++i;
inboundShipmentUpdate.save();
}
catch(err)
{
var msg = '';
log.debug("There was an error", err);
}
})
return "";
}
Does anyone have any idea why everything is coming back empty for me when I try to use NetSuite's methods, but showing correctly when I read the actual record's JSON?
I made this much more difficult than I needed to. I used the findSublistLineWithValue function, and was able to get the correct line value (it WAS 0, for whatever reason the json of the object was coming back with two entries, the first being empty values, so I incorrectly assumed that was line 0). I also had to compare against an actual string instead of a value, or I would get -1.
var lineNumber = inboundShipmentUpdate.findSublistLineWithValue({
sublistId: 'items',
fieldId: 'itemid',
value: itemID.toString()
});
Once I did this, I was able to get the correct values using my other methods. I just really dumbed down my api calls, and that helped me figure out what was going on.

Nested Promises in node.js and pg

I am new to node and writing a small application. I haven't used a language as asynchronous as this on the server before and have myself in a bit of a pickle. I need to take a string, query a table for an id, then insert in a second table using the result, then return a string from the funtion two levels up. I have a custom dao I use for the db stuff. Here is the function where it all happens:
function generateToken(data, userId, client) {
var random = Math.floor(Math.random() * 100001);
var sha256 = crypto.createHmac("sha256", random );
var token = sha256.update(data).digest("base64");
var query = dao.select(
'auth.apps',
{
name: client.name,
version: client.version,
subversion: client.subversion,
patch: client.patch
}
).done(
function(result) {
dao.insert(
'auth.tokens',
{
user_id:userId,
app_id: result.rows[0].id,
token:token
}
);
return "mmmm yellllo";
}
);
var ret_val = await(query);
console.log("Token return: " + ret_val);
return ret_val;
}
and here is the relevant part of my dao for select:
dbo.prototype.select = function(table, where, order_by) {
var where_clause = this.construct_where(where);
var sql = 'SELECT * FROM ' + table + ' WHERE ' + where_clause;
if(order_by !== undefined) {
sql = sql + ' ORDER BY ' + order_by;
};
var result = this.pool.query(sql);
return result;
};
and insert:
dbo.prototype.insert= function(table, values) {
var key_list='', value_list = '';
for( var k in values)
{
key_list = key_list + ', ' + k;
value_list = value_list + ", '" + values[k] + "'";
}
// chop off comma space
key_list = key_list.substring(2);
value_list = value_list.substring(2);
var sql = 'INSERT INTO ' + table + '(' + key_list + ') VALUES(' + value_list + ') RETURNING id';
var result = this.pool.query(sql).catch(function(error) {
console.log("SQL:" + sql + " error:" + error);
});
return result;
};
How do unwind the double promise. I want the generateToken function to return the token variable but only after the insert query has finished.
There is a library named deasync.
And the motivation to create it was to solve the situations when
API cannot be changed to return merely a promise or demand a callback
parameter
So this is the primary and probably the only use case. Because in general Node.js should stay async.
To do the trick you basically should write a function that accepts a callback and then wrap it with deasync as follows:
var deasync = require('deasync');
//It can still take the params before the callback
var asyncGenerateToken = function (data, userId, client, callback) {
var token = 'abc';
//Async operation starts here
setTimeout(function () {
//Async operation is finished, now we can return the token
//Don't forget that the error is 1st arg, data is the 2nd
callback(null, token);
}, 1000);
};
var generateToken = deasync(asyncGenerateToken);
//We'll retrieve a token only after a second of waiting
var token = generateToken('my data', 'my user id', 'my client');
console.log(token);
Hope this helps.

I am trying to develop a specific adapter for sqlite3 with node.js This is similar sails-mysql as devised. I do not know how to start

OracleDialect.prototype.describe = function (connection, collection, callback) {
var tableName = this.normalizeTableName(collection.tableName);
var queries = [];
queries[0] = "SELECT COLUMN_NAME, DATA_TYPE, NULLABLE FROM USER_TAB_COLUMNS WHERE TABLE_NAME = '" + tableName + "'";
queries[1] = "SELECT index_name,COLUMN_NAME FROM user_ind_columns WHERE table_name = '" + tableName + "'";
queries[2] = "SELECT cols.table_name, cols.column_name, cols.position, cons.status, cons.owner "
+ "FROM all_constraints cons, all_cons_columns cols WHERE cols.table_name = '" + tableName
+ "' AND cons.constraint_type = 'P' AND cons.constraint_name = cols.constraint_name AND cons.owner = cols.owner "
+ "ORDER BY cols.table_name, cols.position";
asynk.each(queries, function (query, nextQuery) {
connection.client.raw(query).asCallback(nextQuery);
}).serie().done(function (results) {
var schema = results[0];
var indexes = results[1];
var tablePrimaryKeys = results[2];
if (schema.length === 0) {
return callback({code: 'ER_NO_SUCH_TABLE', message: 'Table ' + tableName + ' doesn\'t exist.'}, null);
}
// Loop through Schema and attach extra attributes
schema.forEach(function (attribute) {
tablePrimaryKeys.forEach(function (pk) {
// Set Primary Key Attribute
if (attribute.COLUMN_NAME === pk.COLUMN_NAME) {
attribute.primaryKey = true;
// If also a number set auto increment attribute
if (attribute.DATA_TYPE === 'NUMBER') {
attribute.autoIncrement = true;
}
}
});
// Set Unique Attribute
if (attribute.NULLABLE === 'N') {
attribute.required = true;
}
});
// Loop Through Indexes and Add Properties
indexes.forEach(function (index) {
schema.forEach(function (attribute) {
if (attribute.COLUMN_NAME === index.COLUMN_NAME)
{
attribute.indexed = true;
}
});
});
//console.log("describe schema: ",schema);
callback(null, schema);
}).fail(function(err) {
return callback(err, null);
});
};
I hope all my questions can be answered with a link to a good documentation!
Thank you!
I hope all my questions can be answered with a link to a good documentation!
this is for orcale adapter

Synchronous Call : Call 2nd function after 1st function is executed completely

I recently stating coding in node.js and might be a very simple question.
Trying to write a XML parser/validator to validate xml schema and values against values/ xpath stored in an excel sheet.
Now once the validation function is complete I want to call a printResult function to print final result. However if I try to call the function immediately after the first function .. its printing variables initial values and if called within the first which is iterating though the number of xpaths present in excel sheet and printing result with increments.
var mocha = require('mocha');
var assert = require('chai').assert;
var fs = require('fs');
var parseString = require('xml2js').parseString;
var xpath = require('xpath');
var dom = require('xmldom').DOMParser;
var XLSX = require('xlsx');
var Excel = require("exceljs");
var should = require('chai').should();
var HashMap = require('hashmap');
var colors = require('colors');
require('/xmlValidator/dbConnect.js');
var map = new HashMap();
var elementMap = new HashMap();
var resultValue;
//console.log('hello'.green);
map.set("PASS", 0);
map.set("FAIL", 0);
map.set("INVALID_PATH", 0);
function computeResult(elementPath, result) {
var pass = map.get("PASS");
var fail = map.get("FAIL");
var invalidPath = map.get("INVALID_PATH");
elementMap.set(elementPath, result);
if (result == "PASS") {
pass++;
map.set("PASS", pass);
} else if (result == "FAIL") {
fail++;
map.set("FAIL", fail);
} else {
invalidPath++;
map.set("INVALID_PATH", invalidPath)
}
printResult();
}
function printResult() {
var pass = map.get("PASS");
var fail = map.get("FAIL");
var invalidPath = map.get("INVALID_PATH");
console.log(("PASS Count :" + pass).green);
console.log(("FAIL Count :" + fail).red);
console.log(("Inavlid Path :" + invalidPath).yellow);
elementMap.forEach(function(value, key) {
if (value == "INVALID_PATH")
console.log((key + ":" + value).yellow);
else if (value == "FAIL")
console.log((key + ":" + value).red);
else
console.log(key + ":" + value);
});
}
var workbook = new Excel.Workbook();
workbook.xlsx.readFile('utils/' + process.argv[2])
.then(function() {
var worksheet = workbook.getWorksheet(1);
worksheet.eachRow(function(row, rowNumber) {
//console.log(rowNumber);
var row = worksheet.getRow(rowNumber);
var dataPath1 = row.getCell("A").value;
var dataPath2 = row.getCell("B").value;
var dataPath = dataPath1 + dataPath2;
//console.log(dataPath);
var dataValue = row.getCell("D").value;
var flag = row.getCell("E").value;
//console.log(flag)
//console.log(dataValue);
if (!flag)
validate(dataPath, dataValue, rowNumber);
//else console.log("NOT EXECUTED" + rowNumber)
});
})
function validate(dataPath, dataValue, rowNumber) {
var fail = 0;
fs.readFile('utils/' + process.argv[3], 'utf8', function(err, data) {
if (err) {
console.log("ERROR ERROR ERROR ERROR ");
return console.log(err);
}
var doc = new dom().parseFromString(data);
var subId = String(xpath.select1(dataPath, doc));
if (subId == "undefined") {
/*console.log('undefined caught');
console.log("row number :" + rowNumber);*/
var resultValue = "INVALID_PATH";
computeResult(dataPath, resultValue);
} else {
var subId = xpath.select1(dataPath, doc);
var value = subId.lastChild.data;
/*console.log("row number :" + rowNumber);
console.log("actual value: " + value);
console.log("expected value:" + dataValue );*/
if (dataValue == null) {
assert.notEqual(value, dataValue, "value not found");
resultValue = "PASS";
computeResult(dataPath, resultValue);
} else {
if (value == dataValue)
resultValue = "PASS";
else resultValue = "FAIL";
computeResult(dataPath, resultValue);
}
}
});
}
In the code above i want to call printResult() function after validate function is completely executed (workbook.xlsx.readFile)
Can some one please help me out how to use done () function or make sync call ?
If fs.readFileAsync('utils/' + process.argv[3], 'utf8') can be executed once, then validate() will be completely synchronous and calling printResult() after the verification loop will be trivial.
In the main routine, you can simply aggregate two promises ...
var promise1 = workbook.xlsx.readFile();
var promise2 = fs.readFileAsync(); // requires `fs` to be promisified.
... before embarking on the verification loop.
Promise.all([promise1, promise2]).spread(/* verify here */);
Also a whole bunch of tidying can be considered, in particular :
establishing "PASS", "FAIL" and "INVALID_PATH" as constants to avoid lots of repetitive string creation,
using js plain objects in lieu of hashmap,
building map from elementMap inside the print function.
having validate() return its result and building elementMap in the main routine
Here's the whole thing, about as tight as I can get it. I may have made a few assumptions but hopefully not too many bad ones ...
var mocha = require('mocha');
var assert = require('chai').assert;
var Promise = require("bluebird");
var fs = Promise.promisifyAll(require("fs")); // allow Bluebird to take the pain out of promisification.
var parseString = require('xml2js').parseString;
var xpath = require('xpath');
var dom = require('xmldom').DOMParser;
var XLSX = require('xlsx');
var Excel = require("exceljs");
var should = require('chai').should();
// var HashMap = require('hashmap');
var colors = require('colors');
require('/xmlValidator/dbConnect.js');
const PASS = "PASS";
const FAIL = "FAIL";
const INVALID_PATH = "INVALID_PATH";
function printResult(elementMap) {
var key, result,
map = { PASS: 0, FAIL: 0, INVALID_PATH: 0 },
colorNames = { PASS: 'black', FAIL: 'red', INVALID_PATH: 'yellow' };
for(key in elementMap) {
result = elementMap[key];
map[(result === PASS || result === FAIL) ? result : INVALID_PATH] += 1;
console.log((key + ": " + result)[colorNames[result] || 'black']); // presumably colors can be applied with associative syntax? If so, then the code can be very concise.
}
console.log(("PASS Count: " + map.PASS)[colorNames.PASS]);
console.log(("FAIL Count: " + map.FAIL)[colorNames.FAIL]);
console.log(("Inavlid Path: " + map.INVALID_PATH)[colorNames.INVALID_PATH]);
}
function validate(doc, dataPath, dataValue) {
var subId = xpath.select1(dataPath, doc),
value = subId.lastChild.data,
result;
if (String(subId) == "undefined") {
result = INVALID_PATH;
} else {
if (dataValue === null) {
assert.notEqual(value, dataValue, "value not found"); // not too sure what this does
result = PASS;
} else {
result = (value === dataValue) ? PASS : FAIL;
}
}
return result;
}
//Main routine
var workbook = new Excel.Workbook();
var promise1 = workbook.xlsx.readFile('utils/' + process.argv[2]); // from the question, workbook.xlsx.readFile() appears to return a promise.
var promise2 = fs.readFileAsync('utils/' + process.argv[3], 'utf8');
Promise.all([promise1, promise2]).spread(function(data2, data3) {
var worksheet = workbook.getWorksheet(1),
doc = new dom().parseFromString(data3),
elementMap = {};
worksheet.eachRow(function(row, rowNumber) {
// var row = worksheet.getRow(rowNumber); // row is already a formal variable ???
var dataPath, dataValue;
if (!row.getCell('E').value)
dataPath = row.getCell('A').value + row.getCell('B').value;
dataValue = row.getCell('D').value;
elementMap[dataPath] = validate(doc, dataPath, dataValue);
});
printResult(elementMap);
});
Untested so may not run but at least you can raid the code for ideas.

Resources