mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-19 19:11:13 +00:00
This commit is contained in:
committed by
GitHub
parent
e1d8eaa170
commit
62f4361f46
@@ -8,13 +8,7 @@ import { DateTime, Duration, Interval, Settings } from 'luxon';
|
||||
import { augmentArray, augmentObject } from './augment-object';
|
||||
import { AGENT_LANGCHAIN_NODE_TYPE, SCRIPTING_NODE_TYPES } from './constants';
|
||||
import { ApplicationError } from '@n8n/errors';
|
||||
import {
|
||||
ExpressionError,
|
||||
type ExpressionErrorOptions,
|
||||
EXPRESSION_ERROR_MESSAGES,
|
||||
EXPRESSION_ERROR_TYPES,
|
||||
EXPRESSION_DESCRIPTION_KEYS,
|
||||
} from './errors/expression.error';
|
||||
import { ExpressionError, type ExpressionErrorOptions } from './errors/expression.error';
|
||||
import { getGlobalState } from './global-state';
|
||||
import { NodeConnectionTypes } from './interfaces';
|
||||
import type {
|
||||
@@ -396,13 +390,11 @@ export class WorkflowDataProxy {
|
||||
}
|
||||
|
||||
if (!that.workflow.getNode(nodeName)) {
|
||||
throw new ExpressionError(EXPRESSION_ERROR_MESSAGES.NODE_NOT_FOUND, {
|
||||
messageTemplate: EXPRESSION_ERROR_MESSAGES.NODE_REFERENCE_TEMPLATE,
|
||||
throw new ExpressionError("Referenced node doesn't exist", {
|
||||
runIndex: that.runIndex,
|
||||
itemIndex: that.itemIndex,
|
||||
nodeCause: nodeName,
|
||||
descriptionKey: EXPRESSION_DESCRIPTION_KEYS.NODE_NOT_FOUND,
|
||||
type: EXPRESSION_ERROR_TYPES.PAIRED_ITEM_NO_CONNECTION,
|
||||
descriptionKey: 'nodeNotFound',
|
||||
});
|
||||
}
|
||||
|
||||
@@ -410,12 +402,11 @@ export class WorkflowDataProxy {
|
||||
!that.runExecutionData.resultData.runData.hasOwnProperty(nodeName) &&
|
||||
!getPinDataIfManualExecution(that.workflow, nodeName, that.mode)
|
||||
) {
|
||||
throw new ExpressionError(EXPRESSION_ERROR_MESSAGES.NODE_NOT_FOUND, {
|
||||
messageTemplate: EXPRESSION_ERROR_MESSAGES.NODE_REFERENCE_TEMPLATE,
|
||||
throw new ExpressionError('Referenced node is unexecuted', {
|
||||
runIndex: that.runIndex,
|
||||
itemIndex: that.itemIndex,
|
||||
type: EXPRESSION_ERROR_TYPES.PAIRED_ITEM_NO_CONNECTION,
|
||||
descriptionKey: EXPRESSION_DESCRIPTION_KEYS.NO_NODE_EXECUTION_DATA,
|
||||
type: 'no_node_execution_data',
|
||||
descriptionKey: 'noNodeExecutionData',
|
||||
nodeCause: nodeName,
|
||||
});
|
||||
}
|
||||
@@ -505,16 +496,11 @@ export class WorkflowDataProxy {
|
||||
name = name.toString();
|
||||
|
||||
if (!node) {
|
||||
throw new ExpressionError(EXPRESSION_ERROR_MESSAGES.NODE_NOT_FOUND, {
|
||||
messageTemplate: EXPRESSION_ERROR_MESSAGES.NODE_REFERENCE_TEMPLATE,
|
||||
functionality: 'pairedItem',
|
||||
descriptionKey: isScriptingNode(nodeName, that.workflow)
|
||||
? EXPRESSION_DESCRIPTION_KEYS.PAIRED_ITEM_NO_CONNECTION_CODE_NODE
|
||||
: EXPRESSION_DESCRIPTION_KEYS.PAIRED_ITEM_NO_CONNECTION,
|
||||
type: EXPRESSION_ERROR_TYPES.PAIRED_ITEM_NO_CONNECTION,
|
||||
nodeCause: nodeName,
|
||||
throw new ExpressionError("Referenced node doesn't exist", {
|
||||
runIndex: that.runIndex,
|
||||
itemIndex: that.itemIndex,
|
||||
nodeCause: nodeName,
|
||||
descriptionKey: 'nodeNotFound',
|
||||
});
|
||||
}
|
||||
|
||||
@@ -530,7 +516,7 @@ export class WorkflowDataProxy {
|
||||
|
||||
if (executionData.length === 0) {
|
||||
if (that.workflow.getParentNodes(nodeName).length === 0) {
|
||||
throw new ExpressionError(EXPRESSION_ERROR_MESSAGES.NO_EXECUTION_DATA, {
|
||||
throw new ExpressionError('No execution data available', {
|
||||
messageTemplate:
|
||||
'No execution data available to expression under ‘%%PARAMETER%%’',
|
||||
descriptionKey: 'noInputConnection',
|
||||
@@ -541,7 +527,7 @@ export class WorkflowDataProxy {
|
||||
});
|
||||
}
|
||||
|
||||
throw new ExpressionError(EXPRESSION_ERROR_MESSAGES.NO_EXECUTION_DATA, {
|
||||
throw new ExpressionError('No execution data available', {
|
||||
runIndex: that.runIndex,
|
||||
itemIndex: that.itemIndex,
|
||||
type: 'no_execution_data',
|
||||
@@ -707,16 +693,11 @@ export class WorkflowDataProxy {
|
||||
const nodeName = name.toString();
|
||||
|
||||
if (that.workflow.getNode(nodeName) === null) {
|
||||
throw new ExpressionError(EXPRESSION_ERROR_MESSAGES.NODE_NOT_FOUND, {
|
||||
messageTemplate: EXPRESSION_ERROR_MESSAGES.NODE_REFERENCE_TEMPLATE,
|
||||
functionality: 'pairedItem',
|
||||
descriptionKey: isScriptingNode(nodeName, that.workflow)
|
||||
? EXPRESSION_DESCRIPTION_KEYS.PAIRED_ITEM_NO_CONNECTION_CODE_NODE
|
||||
: EXPRESSION_DESCRIPTION_KEYS.PAIRED_ITEM_NO_CONNECTION,
|
||||
type: EXPRESSION_ERROR_TYPES.PAIRED_ITEM_NO_CONNECTION,
|
||||
nodeCause: nodeName,
|
||||
throw new ExpressionError("Referenced node doesn't exist", {
|
||||
runIndex: that.runIndex,
|
||||
itemIndex: that.itemIndex,
|
||||
nodeCause: nodeName,
|
||||
descriptionKey: 'nodeNotFound',
|
||||
});
|
||||
}
|
||||
|
||||
@@ -833,14 +814,14 @@ export class WorkflowDataProxy {
|
||||
});
|
||||
};
|
||||
|
||||
const createNodeReferenceError = (nodeCause: string) => {
|
||||
return createExpressionError(EXPRESSION_ERROR_MESSAGES.NODE_NOT_FOUND, {
|
||||
messageTemplate: EXPRESSION_ERROR_MESSAGES.NODE_REFERENCE_TEMPLATE,
|
||||
const createNoConnectionError = (nodeCause: string) => {
|
||||
return createExpressionError('Invalid expression', {
|
||||
messageTemplate: 'No path back to referenced node',
|
||||
functionality: 'pairedItem',
|
||||
descriptionKey: isScriptingNode(nodeCause, that.workflow)
|
||||
? EXPRESSION_DESCRIPTION_KEYS.PAIRED_ITEM_NO_CONNECTION_CODE_NODE
|
||||
: EXPRESSION_DESCRIPTION_KEYS.PAIRED_ITEM_NO_CONNECTION,
|
||||
type: EXPRESSION_ERROR_TYPES.PAIRED_ITEM_NO_CONNECTION,
|
||||
? 'pairedItemNoConnectionCodeNode'
|
||||
: 'pairedItemNoConnection',
|
||||
type: 'paired_item_no_connection',
|
||||
moreInfoLink: true,
|
||||
nodeCause,
|
||||
});
|
||||
@@ -1009,7 +990,7 @@ export class WorkflowDataProxy {
|
||||
const matchedItems = results.filter((result) => result.ok).map((result) => result.result);
|
||||
|
||||
if (matchedItems.length === 0) {
|
||||
if (sourceArray.length === 0) throw createNodeReferenceError(destinationNodeName);
|
||||
if (sourceArray.length === 0) throw createNoConnectionError(destinationNodeName);
|
||||
throw createBranchNotFoundError(sourceData.previousNode, pairedItem.item, nodeBeforeLast);
|
||||
}
|
||||
|
||||
@@ -1050,7 +1031,7 @@ export class WorkflowDataProxy {
|
||||
inputData?.[NodeConnectionTypes.AiTool]?.[0]?.[itemIndex].json;
|
||||
|
||||
if (!placeholdersDataInputData) {
|
||||
throw new ExpressionError(EXPRESSION_ERROR_MESSAGES.NO_EXECUTION_DATA, {
|
||||
throw new ExpressionError('No execution data available', {
|
||||
runIndex,
|
||||
itemIndex,
|
||||
type: 'no_execution_data',
|
||||
@@ -1072,7 +1053,12 @@ export class WorkflowDataProxy {
|
||||
|
||||
const referencedNode = that.workflow.getNode(nodeName);
|
||||
if (referencedNode === null) {
|
||||
throw createNodeReferenceError(nodeName);
|
||||
throw createExpressionError("Referenced node doesn't exist", {
|
||||
runIndex: that.runIndex,
|
||||
itemIndex: that.itemIndex,
|
||||
nodeCause: nodeName,
|
||||
descriptionKey: 'nodeNotFound',
|
||||
});
|
||||
}
|
||||
|
||||
const ensureNodeExecutionData = () => {
|
||||
@@ -1080,38 +1066,16 @@ export class WorkflowDataProxy {
|
||||
!that?.runExecutionData?.resultData?.runData.hasOwnProperty(nodeName) &&
|
||||
!getPinDataIfManualExecution(that.workflow, nodeName, that.mode)
|
||||
) {
|
||||
// Always show helpful "Execute node for preview" message
|
||||
throw new ExpressionError(EXPRESSION_ERROR_MESSAGES.NO_EXECUTION_DATA, {
|
||||
messageTemplate: `Execute node "${nodeName}" for preview`,
|
||||
nodeCause: nodeName,
|
||||
throw createExpressionError('Referenced node is unexecuted', {
|
||||
runIndex: that.runIndex,
|
||||
itemIndex: that.itemIndex,
|
||||
type: 'no_node_execution_data',
|
||||
descriptionKey: 'noNodeExecutionData',
|
||||
nodeCause: nodeName,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const ensureValidPath = () => {
|
||||
// Check path before execution data
|
||||
const referencedNode = that.workflow.getNode(nodeName);
|
||||
if (!referencedNode) {
|
||||
throw createNodeReferenceError(nodeName);
|
||||
}
|
||||
|
||||
const activeNode = that.workflow.getNode(that.activeNodeName);
|
||||
let contextNode = that.contextNodeName;
|
||||
if (activeNode) {
|
||||
const parentMainInputNode = that.workflow.getParentMainInputNode(activeNode);
|
||||
contextNode = parentMainInputNode?.name ?? contextNode;
|
||||
}
|
||||
|
||||
// For .first(), .last(), .all() methods, use unidirectional path checking
|
||||
// (forward only) to maintain traditional paired item behavior
|
||||
const hasForwardPath = that.workflow.getChildNodes(nodeName).includes(contextNode);
|
||||
if (!hasForwardPath) {
|
||||
throw createNodeReferenceError(nodeName);
|
||||
}
|
||||
};
|
||||
|
||||
return new Proxy(
|
||||
{},
|
||||
{
|
||||
@@ -1144,24 +1108,17 @@ export class WorkflowDataProxy {
|
||||
property === PAIRED_ITEM_METHOD.ITEM
|
||||
) {
|
||||
// Before resolving the pairedItem make sure that the requested node comes in the
|
||||
// graph before the current one or exists in the workflow
|
||||
const referencedNode = that.workflow.getNode(nodeName);
|
||||
if (!referencedNode) {
|
||||
// Node doesn't exist in the workflow (could be trimmed manual execution)
|
||||
throw createNodeReferenceError(nodeName);
|
||||
}
|
||||
|
||||
// graph before the current one
|
||||
const activeNode = that.workflow.getNode(that.activeNodeName);
|
||||
|
||||
let contextNode = that.contextNodeName;
|
||||
if (activeNode) {
|
||||
const parentMainInputNode = that.workflow.getParentMainInputNode(activeNode);
|
||||
contextNode = parentMainInputNode?.name ?? contextNode;
|
||||
contextNode = parentMainInputNode.name ?? contextNode;
|
||||
}
|
||||
|
||||
// Use bidirectional path checking to handle AI/tool nodes properly
|
||||
if (!that.workflow.hasPath(nodeName, contextNode)) {
|
||||
throw createNodeReferenceError(nodeName);
|
||||
const parentNodes = that.workflow.getParentNodes(contextNode);
|
||||
if (!parentNodes.includes(nodeName)) {
|
||||
throw createNoConnectionError(nodeName);
|
||||
}
|
||||
|
||||
ensureNodeExecutionData();
|
||||
@@ -1242,7 +1199,6 @@ export class WorkflowDataProxy {
|
||||
}
|
||||
|
||||
if (property === 'first') {
|
||||
ensureValidPath();
|
||||
ensureNodeExecutionData();
|
||||
return (branchIndex?: number, runIndex?: number) => {
|
||||
branchIndex =
|
||||
@@ -1261,7 +1217,6 @@ export class WorkflowDataProxy {
|
||||
};
|
||||
}
|
||||
if (property === 'last') {
|
||||
ensureValidPath();
|
||||
ensureNodeExecutionData();
|
||||
return (branchIndex?: number, runIndex?: number) => {
|
||||
branchIndex =
|
||||
@@ -1283,7 +1238,6 @@ export class WorkflowDataProxy {
|
||||
};
|
||||
}
|
||||
if (property === 'all') {
|
||||
ensureValidPath();
|
||||
ensureNodeExecutionData();
|
||||
return (branchIndex?: number, runIndex?: number) => {
|
||||
branchIndex =
|
||||
@@ -1322,7 +1276,7 @@ export class WorkflowDataProxy {
|
||||
if (property === 'isProxy') return true;
|
||||
|
||||
if (that.connectionInputData.length === 0) {
|
||||
throw createExpressionError(EXPRESSION_ERROR_MESSAGES.NO_EXECUTION_DATA, {
|
||||
throw createExpressionError('No execution data available', {
|
||||
runIndex: that.runIndex,
|
||||
itemIndex: that.itemIndex,
|
||||
type: 'no_execution_data',
|
||||
|
||||
Reference in New Issue
Block a user