From e4528b53f7239e1ae23d31b8bd75086f7c30a25e Mon Sep 17 00:00:00 2001 From: shulkaolka Date: Fri, 26 Sep 2025 14:27:14 +0300 Subject: [PATCH 1/2] add support for array splitting in action responses and improve logging --- templates/lib/actions/action.js | 82 +++++++++++++++++++++++++++------ 1 file changed, 67 insertions(+), 15 deletions(-) diff --git a/templates/lib/actions/action.js b/templates/lib/actions/action.js index e27e7cb..b06cdf7 100644 --- a/templates/lib/actions/action.js +++ b/templates/lib/actions/action.js @@ -12,7 +12,14 @@ */ const spec = require("../spec.json"); -const { mapFieldNames, getMetadata, mapFormDataBody, putAdditionalParamsInBody, executeCall, formatApiKey } = require("../utils/helpers"); +const { + mapFieldNames, + getMetadata, + mapFormDataBody, + putAdditionalParamsInBody, + executeCall, + formatApiKey, +} = require("../utils/helpers"); const componentJson = require("../../component.json"); async function processAction(msg, cfg, snapshot, incomingMessageHeaders, tokenData) { @@ -23,7 +30,6 @@ async function processAction(msg, cfg, snapshot, incomingMessageHeaders, tokenDa if (cfg && cfg.nodeSettings && cfg.nodeSettings.continueOnError) continueOnError = true; try { - if (["fatal", "error", "warn", "info", "debug", "trace"].includes(logLevel)) { logger = this.logger.child({}); logger.level && logger.level(logLevel); @@ -114,31 +120,77 @@ async function processAction(msg, cfg, snapshot, incomingMessageHeaders, tokenDa delete callParams.requestBody; } - const resp = await executeCall.call(this, callParams); // Wait for rate limit if specified - const rateLimit = cfg.nodeSettings && cfg.nodeSettings.rateLimit ? parseInt(cfg.nodeSettings.rateLimit) : (Number.isInteger(componentJson.rateLimit) ? componentJson.rateLimit : 0); + const rateLimit = + cfg.nodeSettings && cfg.nodeSettings.rateLimit + ? parseInt(cfg.nodeSettings.rateLimit) + : Number.isInteger(componentJson.rateLimit) + ? componentJson.rateLimit + : 0; if (rateLimit > 0) { this.logger.info(`Waiting for rate limit: ${rateLimit} ms`); - await new Promise(resolve => setTimeout(resolve, rateLimit)); + await new Promise((resolve) => setTimeout(resolve, rateLimit)); } - const newElement = {}; - newElement.metadata = getMetadata(msg.metadata); - newElement.data = resp.body; + const responseBody = resp.body; + const { arraySplittingKey } = cfg.nodeSettings; + + if (arraySplittingKey && !cfg.returnResult) { + if (Array.isArray(responseBody)) { + logger.info(`Response is an array with ${responseBody.length} items. Emitting each element separately.`); + responseBody.forEach((item, index) => { + this.emit("data", { + data: item, + metadata: getMetadata(msg.metadata), + }); + logger.info(`Emitted array item at index ${index}`); + }); + } else if (responseBody && typeof responseBody === "object") { + logger.info(`Response is an object. Checking for array at key "${arraySplittingKey}".`); + const splitArray = responseBody[arraySplittingKey]; + + if (Array.isArray(splitArray)) { + logger.info(`Found array at "${arraySplittingKey}" with ${splitArray.length} items. Emitting each element.`); + splitArray.forEach((item, index) => { + this.emit("data", { + data: item, + metadata: getMetadata(msg.metadata), + }); + logger.info(`Emitted nested array item at index ${index}`); + }); + } else { + if (splitArray === undefined) { + logger.info(`Key "${arraySplittingKey}" not found in response object. Emitting full response instead.`); + } else { + logger.info(`Key "${arraySplittingKey}" exists but value is not an array (type: ${typeof splitArray}). Emitting full response instead.`); + } + this.emit("data", { data: responseBody, metadata: getMetadata(msg.metadata) }); + } + } else { + logger.info(`Array splitting key "${arraySplittingKey}" was specified, but response is neither an array nor an object. Type: ${typeof responseBody}. Emitting full response.`); + this.emit("data", { data: responseBody, metadata: getMetadata(msg.metadata) }); + } + } else { + const outputMessage = { + metadata: getMetadata(msg.metadata), + data: responseBody, + }; + + if (cfg.returnResult) { + logger.info(`returnResult flag is true. Returning output message instead of emitting.`); + return outputMessage; + } - if (cfg.returnResult) { - return newElement; + this.emit("data", outputMessage); + this.logger.info("Execution finished: emitted single message."); } - - this.emit("data", newElement); - this.logger.info("Execution finished"); } catch (e) { if (continueOnError === true) { - this.emit('data', { data: {}, metadata: {} }); + this.emit("data", { data: {}, metadata: {} }); } else { - this.emit('error', e); + this.emit("error", e); } logger.error(e); } From 74a8935e110e0e333348384157653f1ce78c1fdf Mon Sep 17 00:00:00 2001 From: shulkaolka Date: Fri, 26 Sep 2025 14:39:56 +0300 Subject: [PATCH 2/2] add support for array splitting in action responses and improve logging --- templates/lib/actions/action.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/templates/lib/actions/action.js b/templates/lib/actions/action.js index b06cdf7..25e9eb5 100644 --- a/templates/lib/actions/action.js +++ b/templates/lib/actions/action.js @@ -148,8 +148,10 @@ async function processAction(msg, cfg, snapshot, incomingMessageHeaders, tokenDa logger.info(`Emitted array item at index ${index}`); }); } else if (responseBody && typeof responseBody === "object") { - logger.info(`Response is an object. Checking for array at key "${arraySplittingKey}".`); - const splitArray = responseBody[arraySplittingKey]; + logger.info(`Response is an object. Resolving nested path "${arraySplittingKey}".`); + const splitArray = arraySplittingKey + .split(".") + .reduce((acc, key) => (acc && acc[key] !== undefined ? acc[key] : null), responseBody); if (Array.isArray(splitArray)) { logger.info(`Found array at "${arraySplittingKey}" with ${splitArray.length} items. Emitting each element.`); @@ -161,10 +163,10 @@ async function processAction(msg, cfg, snapshot, incomingMessageHeaders, tokenDa logger.info(`Emitted nested array item at index ${index}`); }); } else { - if (splitArray === undefined) { - logger.info(`Key "${arraySplittingKey}" not found in response object. Emitting full response instead.`); + if (splitArray === null) { + logger.info(`Path "${arraySplittingKey}" not found in response object. Emitting full response instead.`); } else { - logger.info(`Key "${arraySplittingKey}" exists but value is not an array (type: ${typeof splitArray}). Emitting full response instead.`); + logger.info(`Path "${arraySplittingKey}" resolved, but value is not an array (type: ${typeof splitArray}). Emitting full response instead.`); } this.emit("data", { data: responseBody, metadata: getMetadata(msg.metadata) }); }