const fs = require('fs');
/**
* @module Utils
* @description Assorted useful utils that are used in many places
* @author Kier Lindsay (syonfox)
* Not realy needed for this project but whatever if your reading this might be useful :)
*/
/***
* A util function to get a value out of ether the body or the query
* @param req the request we want to look at
* @param key the key to check req.body and req.params for
*/
module.exports.reqGetData = (req, key) => {
let value = undefined;
if (typeof req.body[key] != "undefined" && req.body[key] != '') {
value = req.body[key]
} else if (typeof req.query[key] != "undefined" && req.query[key] != '') {
value = req.query[key]
}
return value;
}
var spawn = require('child_process').spawn;
/**
* Execute and logs stdout/err (spans a process internally and returns it)
* @param sh - the shell command as you would type it
* @param cb - cb(data, done) whenever stdout is received
*/
module.exports.simpleExec = (sh, cb) => {
let args = sh.split(' ');
let cmd = args.shift();
console.log("Spawning: ", sh);
let proc = spawn(cmd, args);
proc.stdout.on('data', function (data) {
console.log(data);
// status(data, false);
cb(data, false);
});
proc.stderr.setEncoding("utf8")
proc.stderr.on('data', function (data) {
// status(data, false, true);
cb(data, false, true);
});
proc.on('close', function () {
// status('Done Executing ' + cmd, true);
cb('Done Executing ' + cmd, true)
});
}
/**
*https://gist.github.com/GuillermoPena/9233069?permalink_comment_id=2364896#gistcomment-2364896
*/
module.exports.fileHash = function (filename, algorithm = 'md5') {
return new Promise((resolve, reject) => {
// Algorithm depends on availability of OpenSSL on platform
// Another algorithms: 'sha1', 'md5', 'sha256', 'sha512' ...
let shasum = crypto.createHash(algorithm);
try {
let s = fs.ReadStream(filename)
s.on('data', function (data) {
shasum.update(data)
})
// making digest
s.on('end', function () {
const hash = shasum.digest('hex')
return resolve(hash);
})
} catch (error) {
return reject('calc fail');
}
});
}
/***
* A function to convert an array of property object to geojson
* @param geomProperty the property that contains the geometry
* @param rows the array of rows
* @returns {{features: [], type: string}} A geojson Feature Collection
*/
module.exports.rowToGeojson = function (geomProperty, rows) {
let features = [];
rows.forEach(row => {
let geom = JSON.parse(row[geomProperty]);
delete row[geomProperty];
let feature = {
type: 'Feature',
geometry: geom,
geometry_name: "geom",
properties: row,
}
features.push(feature);
});
let geojson = {
type: 'FeatureCollection',
features: features
}
return geojson;
}
/***
* Tries to pares an object out of json returns false if it fails
* @param jsonString
* @return {boolean|any}
*/
module.exports.tryParseJSON = function (jsonString) {
try {
var o = JSON.parse(jsonString);
// Handle non-exception-throwing cases:
// Neither JSON.parse(false) or JSON.parse(1234) throw errors, hence the type-checking,
// but... JSON.parse(null) returns null, and typeof null === "object",
// so we must check for that, too. Thankfully, null is falsey, so this suffices:
if (o && typeof o === "object") {
return o;
}
} catch (e) {
}
return false;
};
/***
* Returns Directory From a source path
* @param source the path
* @returns {*} the fs directory
*/
module.exports.getDirectories = (source) => {
return fs.readdirSync(source, {withFileTypes: true})
.filter(dirent => dirent.isDirectory())
.map(dirent => dirent.name)
}
/**
* Groups array by key https://stackoverflow.com/questions/14446511/most-efficient-method-to-groupby-on-an-array-of-objects
* @param {Array} xs the array to group
* @param {string} key the key to groupby
* @return {Object}
*/
module.exports.groupBy = (xs, key) => {
return xs.reduce(function (rv, x) {
(rv[x[key]] = rv[x[key]] || []).push(x);
return rv;
}, {});
}
/**
* Undoes what groupBy() does
* @param {Object} grp - Object with arrays of values
* @return {Array} -the original arrays
*/
module.exports.unGroup = (grp) => {
// let keys = Object.keys(grp);
// let array = [];
// keys.forEach(k => {
// array = [...grp[k], ...array]
// })
// //[...Object.entries(grp).map((v, k) => v)];
// return array
return Object.values(grp).flat(2);
}
/**
* @name RetObject
* this is my standard way of returning stuff success tells you wether the function successfuly executed or not, msg: is a frendly message of what happened
* data is any data you wish to return and debug is for debug error messaged or any other developer data
*/
class RetObject {
/**
*
* @param {boolean} success - true if function executed successfully
* @param {string} msg - a nice message of what happened
* @param {*} [data] - return data
* @param {*} [debug] - any developer data
*/
constructor(success, msg, data, debug) {
this.success = success;
this.msg = msg;
this.data = data;
this.debug = debug;
}
}
module.exports.to_pgtimestamp = (date) => {
//https://stackoverflow.com/questions/847185/convert-a-unix-timestamp-to-time-in-javascript
// Create a new JavaScript Date object based on the timestamp
// multiplied by 1000 so that the argument is in milliseconds, not seconds.
var date = new Date(date);
var year = date.getFullYear();
var month = date.getMonth()+1;
var day = date.getDate();
// Hours part from the timestamp
var hours = date.getHours();
// Minutes part from the timestamp
var minutes = "0" + date.getMinutes();
// Seconds part from the timestamp
var seconds = "0" + date.getSeconds();
var formattedTime = year + '-' + month + '-' + day + ' ' + hours + ':' + minutes.substr(-2) + ':' + seconds.substr(-2);
console.log(formattedTime);
return formattedTime
}
module.exports.RetObject = RetObject;
/**
* Execute a slq statement on a pg pool or client
* @param {pg.Pool | pg.Client} pg - the pool or client to use to execute the statement.
* @param {string} stmt - the sql statement to execute
* @param {string} [successMsg] - The message to send on success
* @return {Promise<RetObject>} - fills in data if success and debug with error if failed;
*/
module.exports.pgExecute = (pg, stmt, successMsg) => {
if (!successMsg) {
successMsg = "Successfully Executed Query"
}
console.debug("PGExecute: ",stmt);
return pg.query(stmt)
.then(out => {
return new RetObject(true, successMsg, out.rows, undefined);
})
.catch(e => {
console.error(e);
return new RetObject(false, e.message +" [details] " +e.detail, undefined, e);
})
}
/**
* Returns a function that logs the params its called with its parameters
* @param str - a prefex string(s)
* @returns {(function(...[*]): void)|*}
*/
module.exports.logfn = (...str) => {
return (...args) => {
console.log(...str," args: ", ...args )
}
}