UNPKG

node-red-contrib-filemaker

Version:

Node-RED FileMaker nodes. These nodes use the FileMaker Data API to connect with a FileMaker database.

199 lines (171 loc) 6.78 kB
"use strict"; const _ = require("lodash"); /** * @function merge * @private * @description merges the objects recieved into a single object. This function will nest the second * parameter sent to it in a payload property. * @param {Object} message The original message object. * @param {Object} payload The object that should be nested into a payload property. * @return {Object} An object with only properties that are not null, undefined, or an empty string. */ const merge = (property, message, payload) => isJson(message[property]) ? _.set(message, property, Object.assign(message[property], payload)) : _.set(message, property, payload); /** * @function castBooleans * @public * @description traverses an object and casts all "true" and "false" strings as the appropriate boolean type. * @param {Object} object The object to map for true and false strings. * @return {Object} an object with true and false strings mapped to their boolean counterparts. */ const castBooleans = object => _.mapValues(object, (value, key, index) => value === "true" || value === "false" ? value === "true" : value ); /** * @function constructParameters * @public * @description composes a object from the values defined in the values parameter. It will * traverse the incoming node message, the node's configuration, and the current context to * construct the appopriate parameters based on the values passed to it. * @param {Object} message The incoming message recieved by the node. * @param {Object} configuration The current node's configuration. * @param {Object} context The node's current context. * @param {Array} values An array of allowed values. * @return {Object} an object with true and false strings mapped to their boolean counterparts. */ const constructParameters = (message, configuration, context, values) => compact( _.map(values, value => { let parameter = {}; const type = configuration[`${value}Type`]; if (type && type !== "msg" && type !== "flow" && type !== "global") { parameter = { [value]: parseJson(configuration[value]) }; } else if (type === "msg") { parameter = { [value]: _.get(message, parseJson(configuration[value]), "") }; } else if (type === "flow") { parameter = { [value]: context.flow.get(configuration[value]) }; } else if (type === "global") { parameter = { [value]: context.global.get(configuration[value]) }; } return parameter; }) ); /** * @function parseJson * @public * @description checks if the passed parameter is valid json. If the value is not json it is * returned without modification. If the parameter is json it is parsed and returned. * @param {Any} values The value to attempt to parse. * @return {Any|Object} a parsed json object or the original value. */ const parseJson = value => (isJson(value) ? JSON.parse(value) : value); /** * @function compact * @private * @description merges properties from an array of objects together while also discarding properties * with null, empty string, or undefined values. If a non json value is passed to this function it is * discarded. * @see discardEmpty * @param {Object|Array} data The array of objects or single object to compact into one object. * @return {Object} An object with only properties that are not null, undefined, or an empty string. */ const compact = data => { const properties = Array.isArray(data) ? _.map(data, object => (isObject(object) ? discardEmpty(object) : {})) : isJson(data) ? [discardEmpty(data)] : [{}]; return Object.assign({}, ...properties); }; /** * @function discardEmpty * @private * @description discard properties that are null, an empty string or undefined. * @param {Object} object The object to be evaluated and modified. * @return {Object} an object with only properties that are not null, undefined, or an empty string. */ const discardEmpty = object => _.pickBy(object, property => _.identity(property) || property === false); /** * @function isObject * @public * @description The isObject function tests incoming data to see if it is null or an object. * @param {Any} value The data to check * @return {Boolean} A boolean result depending on if the data passed to it is an object */ const isObject = value => value !== null && typeof value === "object"; /** * @function isJson * @public * @description The isJson function uses tests the incoming value to see if * it is json or a string. This function will than attempt to parse the * incoming value. If parsing fails it will return false. If the resulting * value is not an object or is null it will return false, otherwise true. * @param {Any} value The value to be evaluated as json. * @return {Boolean} A boolean result depending on if the value passed to it is valid JSON */ const isJson = value => { value = typeof value !== "string" ? JSON.stringify(value) : value; try { value = JSON.parse(value); } catch (e) { return false; } return isObject(value) ? true : false; }; /** * @function sanitize * @public * @description picks only the properties passed to it from the object it recieves. * @param {Object} object The object to use when picking properties. * @param {Array} properties An array of properties to pick. * @return {Object} A json object with only the properties specified. */ const sanitize = (object, properties) => _.pick(object, properties); /** * @function send * @public * @description handles setting node status and merging properties for when a node sends * a message. * @param {Object} node The node to use when setting status and sending message. * @param {String} output The property to use updating the message. * @param {Object} message The current message object. * @param {Object} response The Data API response * @see {@link merge} */ const send = (node, output, message, response) => { node.status({ fill: "green", shape: "dot", text: "Ready" }); node.send(merge(output, message, response)); }; /** * @function handleError * @public * @description handles errors triggered by a node. This function also sets the nodes' * status for visual feedback. * @param {Object} node The node to use when setting status and sending message. * @param {String} error The error message recieved * @param {Object} message The current message object. */ const handleError = (node, error, message) => { node.status({ fill: "red", shape: "dot", text: error }); node.error(error, message); }; module.exports = { compact, merge, isJson, sanitize, constructParameters, castBooleans, send, handleError };