Add field

This commit is contained in:
Charlie Kolb 2024-11-07 14:24:44 +01:00
parent ddbb263dce
commit 50ca48b480
No known key found for this signature in database
9 changed files with 28 additions and 8 deletions

View file

@ -1,5 +1,5 @@
import { DateTime } from 'luxon';
import type { CodeExecutionMode, IDataObject } from 'n8n-workflow';
import { MANUAL_TRIGGER_NODE_TYPE, type CodeExecutionMode, type IDataObject } from 'n8n-workflow';
import fs from 'node:fs';
import { builtinModules } from 'node:module';
@ -197,6 +197,7 @@ describe('JsTaskRunner', () => {
['$nodeVersion', 2],
['$prevNode.name', 'Trigger'],
['$prevNode.outputIndex', 0],
['$prevNode.nodeType', MANUAL_TRIGGER_NODE_TYPE],
['$runIndex', 0],
['{ wf: $workflow }', { wf: { active: true, id: '1', name: 'Test Workflow' } }],
['$vars', { var: 'value' }],

View file

@ -130,6 +130,7 @@ export class BuiltInsParser {
} else if (node.name === '$execution') {
state.markExecutionAsNeeded();
} else if (node.name === '$prevNode') {
// @Reviewer: Does us using workflow.getNodeByName() affect this?
state.markPrevNodeAsNeeded();
}
};

View file

@ -11,6 +11,7 @@ import type {
* Strips data from data request response based on the specified parameters
*/
export class DataRequestResponseStripper {
// @Reviewer: Same question here, do we need this for node types? Maybe not since they're more "default" than node names?
private requestedNodeNames = new Set<string>();
constructor(

View file

@ -10,7 +10,7 @@ export function usePrevNodeCompletions(matcher = DEFAULT_MATCHER) {
const i18n = useI18n();
/**
* Complete `$prevNode.` to `.name .outputIndex .runIndex`.
* Complete `$prevNode.` to `.name .outputIndex .runIndex .nodeType`.
*/
const prevNodeCompletions = (context: CompletionContext): CompletionResult | null => {
const pattern = new RegExp(`${escape(matcher)}\..*`);
@ -32,6 +32,10 @@ export function usePrevNodeCompletions(matcher = DEFAULT_MATCHER) {
label: `${matcher}.runIndex`,
info: i18n.baseText('codeNodeEditor.completer.$prevNode.runIndex'),
},
{
label: `${matcher}.nodeType`,
info: i18n.baseText('codeNodeEditor.completer.$prevNode.nodeType'),
},
];
return {

View file

@ -1040,6 +1040,11 @@ export const prevNodeOptions = () => {
returnType: 'number',
description: i18n.baseText('codeNodeEditor.completer.$prevNode.runIndex'),
},
{
name: 'nodeType',
returnType: 'string',
description: i18n.baseText('codeNodeEditor.completer.$prevNode.nodeType'),
},
].map((doc) => createCompletionOption({ name: doc.name, doc }));
};

View file

@ -22,6 +22,7 @@ describe('prevNodeCompletions', () => {
expect.objectContaining({ label: '$prevNode.name' }),
expect.objectContaining({ label: '$prevNode.outputIndex' }),
expect.objectContaining({ label: '$prevNode.runIndex' }),
expect.objectContaining({ label: '$prevNode.nodeType' }),
]),
);
});
@ -44,6 +45,7 @@ describe('prevNodeCompletions', () => {
expect.objectContaining({ label: '$prevNode.name' }),
expect.objectContaining({ label: '$prevNode.outputIndex' }),
expect.objectContaining({ label: '$prevNode.runIndex' }),
expect.objectContaining({ label: '$nodeType.runIndex' }),
]),
);
});

View file

@ -253,6 +253,7 @@
"codeNodeEditor.completer.$prevNode.name": "The name of the node that the current input came from. \n\nAlways uses the current node's first input connector if there is more than one (e.g. in the 'Merge' node).",
"codeNodeEditor.completer.$prevNode.outputIndex": "The index of the output connector that the current input came from. Use this when the previous node had multiple outputs (such as an 'If' or 'Switch' node). \n\nAlways uses the current node's first input connector if there is more than one (e.g. in the 'Merge' node).",
"codeNodeEditor.completer.$prevNode.runIndex": "The run of the previous node that generated the current input. \n\nAlways uses the current node's first input connector if there is more than one (e.g. in the 'Merge' node). ",
"codeNodeEditor.completer.$prevNode.nodeType": "The node type of the previous node that generated the current input. \n\nAlways uses the current node's first input connector if there is more than one (e.g. in the 'Merge' node). ",
"codeNodeEditor.completer.$runIndex": "The index of the current run of the current node execution. Starts at 0.",
"codeNodeEditor.completer.$nodeVersion": "The version of the current node (as displayed at the bottom of the nodes's settings pane)",
"codeNodeEditor.completer.$today": "A DateTime representing midnight at the start of the current day. \n\nUses the instance's time zone (unless overridden in the workflow's settings).",

View file

@ -500,7 +500,7 @@ export class WorkflowDataProxy {
}
private prevNodeGetter() {
const allowedValues = ['name', 'outputIndex', 'runIndex'];
const allowedValues = ['name', 'outputIndex', 'runIndex', 'nodeType'];
const that = this;
return new Proxy(
@ -528,12 +528,12 @@ export class WorkflowDataProxy {
if (name === 'name') {
return sourceData.previousNode;
}
if (name === 'outputIndex') {
} else if (name === 'outputIndex') {
return sourceData.previousNodeOutput || 0;
}
if (name === 'runIndex') {
} else if (name === 'runIndex') {
return sourceData.previousNodeRun || 0;
} else if (name === 'nodeType') {
return that.workflow.getNode(sourceData.previousNode)?.type || '';
}
return Reflect.get(target, name, receiver);

View file

@ -196,7 +196,12 @@ describe('WorkflowDataProxy', () => {
});
test('$prevNode', () => {
expect(proxy.$prevNode).toEqual({ name: 'Rename', outputIndex: 0, runIndex: 0 });
expect(proxy.$prevNode).toEqual({
name: 'Rename',
outputIndex: 0,
runIndex: 0,
nodeType: 'test.set',
});
});
test('$runIndex', () => {