diff --git a/docs/node-basics.md b/docs/node-basics.md index 0895565d8..f81fb6fce 100644 --- a/docs/node-basics.md +++ b/docs/node-basics.md @@ -52,8 +52,9 @@ The following special variables are available: - **$env**: Environment variables - **$items**: Environment variables - **$json**: Incoming JSON data of a node - - **$node**: Data of other nodes (context, output-data, parameters) + - **$node**: Data of other nodes (binary, context, json, parameter, runIndex) - **$parameters**: Parameters of the current node + - **$runIndex**: The current run index (first time node gets executed it is 0, second time 1, ...) - **$workflow**: Returns workflow metadata like: active, id, name Normally it is not needed to write the JavaScript variables manually as they can be simply selected with the help of the Expression Editor. diff --git a/docs/nodes.md b/docs/nodes.md index 95d910538..9a5e4b577 100644 --- a/docs/nodes.md +++ b/docs/nodes.md @@ -59,7 +59,7 @@ return newItems; ``` -#### Method: $item(index: number) +#### Method: $item(index: number, runIndex?: number) With `$item` it is possible to access the data of parent nodes. That can be the item data but also the parameters. It expects as input an index of the item the data should be returned for. This is @@ -71,6 +71,12 @@ emails at once to different people. Instead, the same person would receive multi The index is 0 based. So `$item(0)` will return the first item, `$item(1)` the second one, ... +By default will the item of the last run of the node be returned. So if the referenced node did run +3x (its last runIndex is 2) and the current node runs the first time (its runIndex is 0) will the +data of runIndex 2 of the referenced node be returned. + +For more information about what data can be accessed via $node check [here](#variable-node). + Example: ```typescript @@ -92,9 +98,9 @@ const channel = $item(9).$node["Slack"].parameter["channel"]; Gives access to all the items of current or parent nodes. If no parameters get supplied it returns all the items of the current node. -If a node-name is given, it returns the items the give node did output. By default of the -first output (index: 0, most nodes only have one output, exceptions are IF and Switch-Node) -and the current run. +If a node-name is given, it returns the items the node did output on it`s first output +(index: 0, most nodes only have one output, exceptions are IF and Switch-Node) on +its last run. Example: @@ -102,22 +108,58 @@ Example: // Returns all the items of the current node and current run const allItems = $items(); -// Returns all items the node "IF" outputs (index: 0 which is Output "true" of current run) +// Returns all items the node "IF" outputs (index: 0 which is Output "true" of its most recent run) const allItems = $items("IF"); -// Returns all items the node "IF" outputs (index: 1 which is Output "false" of run 0 which is the first one) +// Returns all items the node "IF" outputs (index: 0 which is Output "true" of the same run as current node) +const allItems = $items("IF", 0, $runIndex); + +// Returns all items the node "IF" outputs (index: 1 which is Output "false" of run 0 which is the first run) const allItems = $items("IF", 1, 0); ``` #### Variable: $node -Works exactly like `$item` with the difference that it will always return the data of the first item. +Works exactly like `$item` with the difference that it will always return the data of the first item and +the last run of the node. ```typescript +// Returns the fileName of binary property "data" of Node "HTTP Request" +const fileName = $node["HTTP Request"].binary["data"]["fileName"]}} + +// Returns the context data "noItemsLeft" of Node "SplitInBatches" +const noItemsLeft = $node["SplitInBatches"].context["noItemsLeft"]; + +// Returns the value of the JSON data property "myNumber" of Node "Set" const myNumber = $node["Set"].json['myNumber']; +// Returns the value of the parameter "channel" of Node "Slack" const channel = $node["Slack"].parameter["channel"]; + +// Returns the index of the last run of Node "HTTP Request" +const runIndex = $node["HTTP Request"].runIndex}} +``` + + +#### Variable: $runIndex + +Contains the index of the current run of the node. + +```typescript +// Returns all items the node "IF" outputs (index: 0 which is Output "true" of the same run as current node) +const allItems = $items("IF", 0, $runIndex); +``` + + +#### Variable: $workflow + +Gives information about the current workflow. + +```typescript +const isActive = $workflow.active; +const workflowId = $workflow.id; +const workflowName = $workflow.name; ``` diff --git a/packages/workflow/src/WorkflowDataProxy.ts b/packages/workflow/src/WorkflowDataProxy.ts index 24c8cc860..aa30470b1 100644 --- a/packages/workflow/src/WorkflowDataProxy.ts +++ b/packages/workflow/src/WorkflowDataProxy.ts @@ -12,6 +12,7 @@ import { export class WorkflowDataProxy { private workflow: Workflow; private runExecutionData: IRunExecutionData | null; + private defaultReturnRunIndex: number; private runIndex: number; private itemIndex: number; private activeNodeName: string; @@ -19,9 +20,10 @@ export class WorkflowDataProxy { - constructor(workflow: Workflow, runExecutionData: IRunExecutionData | null, runIndex: number, itemIndex: number, activeNodeName: string, connectionInputData: INodeExecutionData[]) { + constructor(workflow: Workflow, runExecutionData: IRunExecutionData | null, runIndex: number, itemIndex: number, activeNodeName: string, connectionInputData: INodeExecutionData[], defaultReturnRunIndex = -1) { this.workflow = workflow; this.runExecutionData = runExecutionData; + this.defaultReturnRunIndex = defaultReturnRunIndex; this.runIndex = runIndex; this.itemIndex = itemIndex; this.activeNodeName = activeNodeName; @@ -130,7 +132,8 @@ export class WorkflowDataProxy { throw new Error(`No execution data found for node "${nodeName}"`); } - runIndex = runIndex === undefined ? that.runIndex : runIndex; + runIndex = runIndex === undefined ? that.defaultReturnRunIndex : runIndex; + runIndex = runIndex === -1 ? (that.runExecutionData.resultData.runData[nodeName].length -1) : runIndex; if (that.runExecutionData.resultData.runData[nodeName].length < runIndex) { throw new Error(`No execution data found for run "${runIndex}" of node "${nodeName}"`); @@ -201,7 +204,7 @@ export class WorkflowDataProxy { name = name.toString(); if (['binary', 'data', 'json'].includes(name)) { - const executionData = that.getNodeExecutionData(nodeName, shortSyntax); + const executionData = that.getNodeExecutionData(nodeName, shortSyntax, undefined); if (executionData.length <= that.itemIndex) { throw new Error(`No data found for item-index: "${that.itemIndex}"`); @@ -241,6 +244,11 @@ export class WorkflowDataProxy { } else if (name === 'parameter') { // Get node parameter data return that.nodeParameterGetter(nodeName); + } else if (name === 'runIndex') { + if (that.runExecutionData === null || !that.runExecutionData.resultData.runData[nodeName]) { + return -1; + } + return that.runExecutionData.resultData.runData[nodeName].length - 1; } return Reflect.get(target, name, receiver); @@ -328,8 +336,9 @@ export class WorkflowDataProxy { $data: {}, // Placeholder $env: this.envGetter(), $evaluateExpression: (expression: string) => { }, // Placeholder - $item: (itemIndex: number) => { - const dataProxy = new WorkflowDataProxy(this.workflow, this.runExecutionData, this.runIndex, itemIndex, this.activeNodeName, this.connectionInputData); + $item: (itemIndex: number, runIndex?: number) => { + const defaultReturnRunIndex = runIndex === undefined ? -1 : runIndex; + const dataProxy = new WorkflowDataProxy(this.workflow, this.runExecutionData, this.runIndex, itemIndex, this.activeNodeName, this.connectionInputData, defaultReturnRunIndex); return dataProxy.getDataProxy(); }, $items: (nodeName?: string, outputIndex?: number, runIndex?: number) => { @@ -339,6 +348,7 @@ export class WorkflowDataProxy { executionData = that.connectionInputData; } else { outputIndex = outputIndex || 0; + runIndex = runIndex === undefined ? -1 : runIndex; executionData = that.getNodeExecutionData(nodeName, false, outputIndex, runIndex); } @@ -347,6 +357,7 @@ export class WorkflowDataProxy { $json: {}, // Placeholder $node: this.nodeGetter(), $parameter: this.nodeParameterGetter(this.activeNodeName), + $runIndex: this.runIndex, $workflow: this.workflowGetter(), };