1
0
mirror of https://github.com/node-red/node-red.git synced 2023-10-10 13:36:53 +02:00
node-red/packages/node_modules/@node-red/editor-client/src/js/hooks.js
2021-05-13 14:00:21 +01:00

157 lines
4.5 KiB
JavaScript

RED.hooks = (function() {
var VALID_HOOKS = [
]
var hooks = { }
var labelledHooks = { }
function add(hookId, callback) {
var parts = hookId.split(".");
var id = parts[0], label = parts[1];
// if (VALID_HOOKS.indexOf(id) === -1) {
// throw new Error("Invalid hook '"+id+"'");
// }
if (label && labelledHooks[label] && labelledHooks[label][id]) {
throw new Error("Hook "+hookId+" already registered")
}
var hookItem = {cb:callback, previousHook: null, nextHook: null }
var tailItem = hooks[id];
if (tailItem === undefined) {
hooks[id] = hookItem;
} else {
while(tailItem.nextHook !== null) {
tailItem = tailItem.nextHook
}
tailItem.nextHook = hookItem;
hookItem.previousHook = tailItem;
}
if (label) {
labelledHooks[label] = labelledHooks[label]||{};
labelledHooks[label][id] = hookItem;
}
}
function remove(hookId) {
var parts = hookId.split(".");
var id = parts[0], label = parts[1];
if ( !label) {
throw new Error("Cannot remove hook without label: "+hookId)
}
if (labelledHooks[label]) {
if (id === "*") {
// Remove all hooks for this label
var hookList = Object.keys(labelledHooks[label]);
for (var i=0;i<hookList.length;i++) {
removeHook(hookList[i],labelledHooks[label][hookList[i]])
}
delete labelledHooks[label];
} else if (labelledHooks[label][id]) {
removeHook(id,labelledHooks[label][id])
delete labelledHooks[label][id];
if (Object.keys(labelledHooks[label]).length === 0){
delete labelledHooks[label];
}
}
}
}
function removeHook(id,hookItem) {
var previousHook = hookItem.previousHook;
var nextHook = hookItem.nextHook;
if (previousHook) {
previousHook.nextHook = nextHook;
} else {
hooks[id] = nextHook;
}
if (nextHook) {
nextHook.previousHook = previousHook;
}
hookItem.removed = true;
if (!previousHook && !nextHook) {
delete hooks[id];
}
}
function trigger(hookId, payload, done) {
var hookItem = hooks[hookId];
if (!hookItem) {
if (done) {
done();
}
return;
}
function callNextHook(err) {
if (!hookItem || err) {
if (done) { done(err) }
return err;
}
if (hookItem.removed) {
hookItem = hookItem.nextHook;
return callNextHook();
}
var callback = hookItem.cb;
if (callback.length === 1) {
try {
let result = callback(payload);
if (result === false) {
// Halting the flow
if (done) { done(false) }
return result;
}
hookItem = hookItem.nextHook;
return callNextHook();
} catch(e) {
console.warn(e);
if (done) { done(e);}
return e;
}
} else {
// There is a done callback
try {
callback(payload,function(result) {
if (result === undefined) {
hookItem = hookItem.nextHook;
callNextHook();
} else {
if (done) { done(result)}
}
})
} catch(e) {
console.warn(e);
if (done) { done(e) }
return e;
}
}
}
return callNextHook();
}
function clear() {
hooks = {}
labelledHooks = {}
}
function has(hookId) {
var parts = hookId.split(".");
var id = parts[0], label = parts[1];
if (label) {
return !!(labelledHooks[label] && labelledHooks[label][id])
}
return !!hooks[id]
}
return {
has: has,
clear: clear,
add: add,
remove: remove,
trigger: trigger
}
})();