first commit
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled

This commit is contained in:
2026-03-17 16:22:57 +03:30
commit 3d5eaf9445
15349 changed files with 2847338 additions and 0 deletions
@@ -0,0 +1,17 @@
{
"node": "n8n-nodes-base.executionData",
"nodeVersion": "1.0",
"codexVersion": "1.0",
"categories": ["Development", "Core Nodes"],
"subcategories": {
"Core Nodes": ["Helpers"]
},
"resources": {
"primaryDocumentation": [
{
"url": "https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.executiondata/"
}
]
},
"alias": ["Filter", "_Set", "Data"]
}
@@ -0,0 +1,156 @@
import type {
IExecuteFunctions,
INodeExecutionData,
INodeType,
INodeTypeDescription,
} from 'n8n-workflow';
import { NodeConnectionTypes, NodeOperationError } from 'n8n-workflow';
type DataToSave = {
values: Array<{ key: string; value: string }>;
};
export class ExecutionData implements INodeType {
description: INodeTypeDescription = {
displayName: 'Execution Data',
name: 'executionData',
icon: 'fa:tasks',
group: ['input'],
iconColor: 'light-green',
version: [1, 1.1],
description: 'Add execution data for search',
defaults: {
name: 'Execution Data',
color: '#29A568',
},
inputs: [NodeConnectionTypes.Main],
outputs: [NodeConnectionTypes.Main],
properties: [
{
displayName:
"Save important data using this node. It will be displayed on each execution for easy reference and you can filter by it.<br />Filtering is available on Pro and Enterprise plans. <a href='https://n8n.io/pricing/' target='_blank'>More Info</a>",
name: 'notice',
type: 'notice',
default: '',
},
{
displayName: 'Operation',
name: 'operation',
type: 'options',
default: 'save',
noDataExpression: true,
options: [
{
name: 'Save Highlight Data (for Search/review)',
value: 'save',
action: 'Save Highlight Data (for search/review)',
},
],
},
{
displayName: 'Data to Save',
name: 'dataToSave',
placeholder: 'Add Saved Field',
type: 'fixedCollection',
typeOptions: {
multipleValueButtonText: 'Add Saved Field',
multipleValues: true,
},
displayOptions: {
show: {
operation: ['save'],
},
},
default: {},
options: [
{
displayName: 'Values',
name: 'values',
values: [
{
displayName: 'Key',
name: 'key',
type: 'string',
default: '',
placeholder: 'e.g. myKey',
requiresDataPath: 'single',
},
{
displayName: 'Value',
name: 'value',
type: 'string',
default: '',
placeholder: 'e.g. myValue',
},
],
},
],
},
],
hints: [
{
type: 'warning',
message: 'Some keys are longer than 50 characters. They will be truncated.',
displayCondition: '={{ $parameter.dataToSave.values.some((x) => x.key.length > 50) }}',
whenToDisplay: 'beforeExecution',
location: 'outputPane',
},
{
type: 'warning',
message: 'Some values are longer than 512 characters. They will be truncated.',
displayCondition: '={{ $parameter.dataToSave.values.some((x) => x.value.length > 512) }}',
whenToDisplay: 'beforeExecution',
location: 'outputPane',
},
],
};
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
const dataProxy = this.getWorkflowDataProxy(0);
const nodeVersion = this.getNode().typeVersion;
const items = this.getInputData();
const operations = this.getNodeParameter('operation', 0);
const returnData: INodeExecutionData[] = [];
if (operations === 'save') {
for (let i = 0; i < items.length; i++) {
try {
const dataToSave =
(this.getNodeParameter('dataToSave', i, {}) as DataToSave).values || [];
const values = dataToSave.reduce(
(acc, { key, value }) => {
const valueToSet = value ? value : nodeVersion >= 1.1 ? '' : value;
acc[key] = valueToSet;
return acc;
},
{} as { [key: string]: string },
);
dataProxy.$execution.customData.setAll(values);
returnData.push(items[i]);
} catch (error) {
if (this.continueOnFail()) {
returnData.push({
json: {
error: error.message,
},
pairedItem: {
item: i,
},
});
continue;
}
throw new NodeOperationError(this.getNode(), error);
}
}
} else {
return [items];
}
return [returnData];
}
}
@@ -0,0 +1,57 @@
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
import { mock } from 'jest-mock-extended';
import type {
IExecuteFunctions,
INodeExecutionData,
IWorkflowDataProxyData,
INode,
} from 'n8n-workflow';
import { ExecutionData } from '../ExecutionData.node';
describe('ExecutionData Node', () => {
it('should return its input data', async () => {
const mockInputData: INodeExecutionData[] = [
{ json: { item: 0, foo: 'bar' } },
{ json: { item: 1, foo: 'quz' } },
];
const executeFns = mock<IExecuteFunctions>({
getInputData: () => mockInputData,
getNode: () => mock<INode>({ typeVersion: 1 }),
});
const result = await new ExecutionData().execute.call(executeFns);
expect(result).toEqual([mockInputData]);
});
it('should set nullish values to empty string', async () => {
const mockInputData: INodeExecutionData[] = [
{ json: { item: 0, foo: undefined } },
{ json: { item: 1, foo: null } },
{ json: { item: 1, foo: 'bar' } },
];
const setAllMock = jest.fn();
const executeFns = mock<IExecuteFunctions>({
getInputData: () => mockInputData,
getWorkflowDataProxy: () =>
mock<IWorkflowDataProxyData>({ $execution: { customData: { setAll: setAllMock } } }),
getNode: () => mock<INode>({ typeVersion: 1.1 }),
});
executeFns.getNodeParameter.mockReturnValueOnce('save');
executeFns.getNodeParameter.mockReturnValueOnce({ values: [{ key: 'foo', value: undefined }] });
executeFns.getNodeParameter.mockReturnValueOnce({ values: [{ key: 'foo', value: null }] });
executeFns.getNodeParameter.mockReturnValueOnce({ values: [{ key: 'foo', value: 'bar' }] });
const result = await new ExecutionData().execute.call(executeFns);
expect(setAllMock).toBeCalledTimes(3);
expect(setAllMock).toBeCalledWith({ foo: '' });
expect(setAllMock).toBeCalledWith({ foo: '' });
expect(setAllMock).toBeCalledWith({ foo: 'bar' });
expect(result).toEqual([mockInputData]);
});
});
describe('ExecutionData -> Should run the workflow', () => {
new NodeTestHarness().setupTests();
});
@@ -0,0 +1,112 @@
{
"name": "[TEST] Execution Data",
"nodes": [
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [60, -240],
"id": "03be3862-c311-48d8-8898-2ffac5fe65b7",
"name": "When clicking Execute workflow"
},
{
"parameters": {
"dataToSave": {
"values": [
{
"key": "id",
"value": "={{ $json.id }}"
}
]
}
},
"type": "n8n-nodes-base.executionData",
"typeVersion": 1,
"position": [480, -240],
"id": "60d009ae-0101-48bd-a0b5-f8d548b22b5d",
"name": "Execution Data"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "ab35ef53-bffd-43d9-99eb-289f3722999d",
"name": "id",
"value": "123456",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [280, -240],
"id": "32447090-1a29-45ab-b967-a80b7222bce4",
"name": "Edit Fields"
},
{
"parameters": {},
"type": "n8n-nodes-base.noOp",
"typeVersion": 1,
"position": [720, -240],
"id": "59e3fc3b-de67-4b2e-9489-a0918c45fc5c",
"name": "No Operation, do nothing"
}
],
"pinData": {
"No Operation, do nothing": [
{
"json": {
"id": "123456"
}
}
]
},
"connections": {
"When clicking Execute workflow": {
"main": [
[
{
"node": "Edit Fields",
"type": "main",
"index": 0
}
]
]
},
"Edit Fields": {
"main": [
[
{
"node": "Execution Data",
"type": "main",
"index": 0
}
]
]
},
"Execution Data": {
"main": [
[
{
"node": "No Operation, do nothing",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "2721b08b-dd2e-4b68-8df7-6c7fedd31e5d",
"meta": {
"instanceId": "8c8c5237b8e37b006a7adce87f4369350c58e41f3ca9de16196d3197f69eabcd"
},
"id": "h6wEFzHoR7UTz8JJ",
"tags": []
}