do-red
Version:
A do-node and corresponding return-node for creating loops and task-lists.
141 lines (131 loc) • 4.93 kB
JavaScript
const isObject = (obj) => (!!obj && typeof obj === 'object' && Array.isArray(obj) === false)
const handleEachArray = (msg) => {
const _do = msg._do
if (_do.yieldType === 'indexValue') {
let newIndex = _do.index
if (!isObject(msg.payload)) {
throw new Error(`Error: Payload is not an object, but should replace index and value for { ${_do.index}: ${_do.collection[_do.index]} }`)
}
newIndex = Object.keys(msg.payload)[0]
if (newIndex !== 'undefined' && isNaN(Number(newIndex))) {
throw new Error(`Error: Payload key is not a number, but should replace { ${_do.index}: ${_do.collection[_do.index]} }`)
}
// check if deleted and and has no delete flag -> then we delete the value from the collection (else)
if (newIndex === 'undefined' && !_do.valueDeleted) {
// const oldValue = _do.collection[_do.index]
_do.collection.splice(_do.index, 1)
// _do.collection = _do.collection.filter(el => el !== oldValue) // check if works with object?!
_do.index = _do.index - 1
_do.valueDeleted = true
_do.collectionLength = _do.collectionLength - 1
// if value was removed in one task and another task wants to add it at the old position again
} else if (_do.valueDeleted && Number(newIndex) === _do.index + 1) {
_do.index = _do.index + 1
_do.collectionLength = _do.collectionLength + 1
_do.collection.splice(_do.index, 0, msg.payload[newIndex])
delete _do.valueDeleted
// set new index/value
} else if (newIndex !== 'undefined') {
_do.collection[newIndex] = msg.payload[newIndex]
// if index was moved, old index will be undefined and not be removed
if (Number(newIndex) !== _do.index) {
_do.collection[_do.index] = undefined
}
}
} else {
_do.collection[_do.index] = msg.payload
}
return msg
}
const handleEachSet = (msg) => {
const _do = msg._do
// if value in Set is an object, we must have the reference of it, which seems to go lost during Node-Red (currentSetValue = set1.values().next() )
// can't delete it with an equal looking object.
if (typeof _do.currentSetValue === 'object') {
const colIterator = _do.collection.values()
for (const el of colIterator) {
if (JSON.stringify(el) === JSON.stringify(_do.currentSetValue)) {
_do.currentSetValue = el
break
}
}
}
_do.collection.delete(_do.currentSetValue)
_do.collection.add(msg.payload)
_do.currentSetValue = msg.payload
return msg
}
const handleEachObject = (msg, RED) => {
const _do = msg._do
const obj = RED.util.getMessageProperty(msg, 'msg._do.collection')
let currentKey = _do.keys[_do.index]
const deleteObject = () => {
delete obj[currentKey]
_do.keys[_do.index] = undefined
}
const changeObject = (newKey, newValue, onlyKey = false) => {
if (currentKey !== newKey) {
obj[newKey] = obj[currentKey]
delete obj[currentKey]
_do.keys[_do.index] = newKey
currentKey = newKey
}
if (!onlyKey) obj[currentKey] = newValue
}
if (_do.yieldType === 'value') {
changeObject(currentKey, msg.payload)
} else if (_do.yieldType === 'key') {
if (msg.payload === undefined) {
deleteObject()
} else {
changeObject(msg.payload, null, true)
}
} else if (_do.yieldType === 'keyValue') {
if (!isObject(msg.payload) && msg.payload !== undefined) {
throw new Error(`Error: Payload is not an object. But should replace { ${currentKey}: ${RED.util.getObjectProperty(obj, currentKey)} }`)
}
if (msg.payload === undefined) {
deleteObject()
} else {
const newKey = Object.keys(msg.payload)[0]
const newValue = msg.payload[newKey]
changeObject(newKey, newValue)
}
}
return msg
}
const handleEachMap = (msg, RED) => {
const _do = msg._do
const thisMap = RED.util.getMessageProperty(msg, 'msg._do.collection')
const currentKey = _do.keys[_do.index]
if (_do.yieldType === 'value') {
thisMap.set(currentKey, msg.payload)
} else if (_do.yieldType === 'key') {
if (msg.payload !== currentKey) {
if (msg.payload !== undefined) thisMap.set(msg.payload, thisMap.get(currentKey))
thisMap.delete(currentKey)
_do.keys[_do.index] = msg.payload
}
} else if (_do.yieldType === 'keyValue') {
if (msg.payload === undefined) {
thisMap.delete(currentKey)
} else {
if (!isObject(msg.payload)) {
throw new Error(`Error: Payload is not an object. But should replace { ${currentKey}: ${RED.util.getObjectProperty(thisMap, currentKey)} }`)
}
const newKey = Object.keys(msg.payload)[0]
if (newKey !== currentKey) {
thisMap.delete(currentKey)
_do.keys[_do.index] = newKey
thisMap.set(newKey, msg.payload[newKey])
}
}
}
return msg
}
module.exports = {
handleEachArray,
handleEachSet,
handleEachObject,
handleEachMap
}