diff --git a/packages/node_modules/@node-red/util/lib/hooks.js b/packages/node_modules/@node-red/util/lib/hooks.js index 19912c7f2..a49104813 100644 --- a/packages/node_modules/@node-red/util/lib/hooks.js +++ b/packages/node_modules/@node-red/util/lib/hooks.js @@ -8,7 +8,12 @@ const VALID_HOOKS = [ "postDeliver", "onReceive", "postReceive", - "onComplete" + "onComplete", + // Module install hooks + "preInstall", + "postInstall", + "preUninstall", + "postUninstall" ] @@ -35,12 +40,12 @@ let labelledHooks = { } * - `postReceive` - passed a `ReceiveEvent` when the message has been given to the node's `input` handler(s) * - `onComplete` - passed a `CompleteEvent` when the node has completed with a message or logged an error * - * @mixin @node-red/runtime_hooks + * @mixin @node-red/util_hooks */ /** * Register a handler to a named hook - * @memberof @node-red/runtime_hooks + * @memberof @node-red/util_hooks * @param {String} hookId - the name of the hook to attach to * @param {Function} callback - the callback function for the hook */ @@ -68,7 +73,7 @@ function add(hookId, callback) { /** * Remove a handled from a named hook - * @memberof @node-red/runtime_hooks + * @memberof @node-red/util_hooks * @param {String} hookId - the name of the hook event to remove - must be `name.label` */ function remove(hookId) { @@ -110,11 +115,33 @@ function removeHook(id,callback) { function trigger(hookId, payload, done) { const hookStack = hooks[hookId]; if (!hookStack || hookStack.length === 0) { - done(); - return; + if (done) { + done(); + return; + } else { + return Promise.resolve(); + } } + if (!done) { + return new Promise((resolve,reject) => { + invokeStack(hookStack,payload,function(err) { + if (err !== undefined && err !== false) { + if (!(err instanceof Error)) { + err = new Error(err); + } + err.hook = hookId + reject(err); + } else { + resolve(err); + } + }) + }); + } else { + invokeStack(hookStack,payload,done) + } +} +function invokeStack(hookStack,payload,done) { let i = 0; - function callNextHook(err) { if (i === hookStack.length || err) { done(err); @@ -148,8 +175,6 @@ function trigger(hookId, payload, done) { } } } - callNextHook(); - function handleResolve(result) { if (result === undefined) { callNextHook(); @@ -157,6 +182,7 @@ function trigger(hookId, payload, done) { done(result); } } + callNextHook(); } function clear() { diff --git a/test/unit/@node-red/util/lib/hooks_spec.js b/test/unit/@node-red/util/lib/hooks_spec.js index d24729070..121486ade 100644 --- a/test/unit/@node-red/util/lib/hooks_spec.js +++ b/test/unit/@node-red/util/lib/hooks_spec.js @@ -249,4 +249,51 @@ describe("util/hooks", function() { done(); }) }) + + + it("handler can use callback function - promise API", function(done) { + hooks.add("onSend.A", function(payload, done) { + setTimeout(function() { + payload.order.push("A") + done() + },30) + }) + hooks.add("onSend.B", function(payload) { payload.order.push("B") } ) + + let data = { order:[] }; + hooks.trigger("onSend",data).then(() => { + data.order.should.eql(["A","B"]) + done() + }).catch(done) + }) + + it("handler can halt execution - promise API", function(done) { + hooks.add("onSend.A", function(payload, done) { + setTimeout(function() { + payload.order.push("A") + done(false) + },30) + }) + hooks.add("onSend.B", function(payload) { payload.order.push("B") } ) + + let data = { order:[] }; + hooks.trigger("onSend",data).then(() => { + data.order.should.eql(["A"]) + done() + }).catch(done) + }) + + it("handler can halt execution on error - promise API", function(done) { + hooks.add("onSend.A", function(payload, done) { + throw new Error("error"); + }) + hooks.add("onSend.B", function(payload) { payload.order.push("B") } ) + + let data = { order:[] }; + hooks.trigger("onSend",data).then(() => { + done("hooks.trigger resolved unexpectedly") + }).catch(err => { + done(); + }) + }) });