mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 10:02:05 +00:00
refactor(Code Node): Constently handle various kinds of data returned by user code (#6002)
This commit is contained in:
committed by
GitHub
parent
fe058aa8ee
commit
f9b3aeac44
@@ -1462,21 +1462,30 @@ export interface IWebhookDescription {
|
||||
restartWebhook?: boolean;
|
||||
}
|
||||
|
||||
export interface ProxyInput {
|
||||
all: () => INodeExecutionData[];
|
||||
context: any;
|
||||
first: () => INodeExecutionData | undefined;
|
||||
item: INodeExecutionData | undefined;
|
||||
last: () => INodeExecutionData | undefined;
|
||||
params?: INodeParameters;
|
||||
}
|
||||
|
||||
export interface IWorkflowDataProxyData {
|
||||
[key: string]: any;
|
||||
$binary: any;
|
||||
$binary: INodeExecutionData['binary'];
|
||||
$data: any;
|
||||
$env: any;
|
||||
$evaluateExpression: any;
|
||||
$item: any;
|
||||
$items: any;
|
||||
$json: any;
|
||||
$evaluateExpression: (expression: string, itemIndex?: number) => NodeParameterValueType;
|
||||
$item: (itemIndex: number, runIndex?: number) => IWorkflowDataProxyData;
|
||||
$items: (nodeName?: string, outputIndex?: number, runIndex?: number) => INodeExecutionData[];
|
||||
$json: INodeExecutionData['json'];
|
||||
$node: any;
|
||||
$parameter: any;
|
||||
$position: any;
|
||||
$parameter: INodeParameters;
|
||||
$position: number;
|
||||
$workflow: any;
|
||||
$: any;
|
||||
$input: any;
|
||||
$input: ProxyInput;
|
||||
$thisItem: any;
|
||||
$thisRunIndex: number;
|
||||
$thisItemIndex: number;
|
||||
|
||||
@@ -24,6 +24,7 @@ import type {
|
||||
INodeParameterResourceLocator,
|
||||
NodeParameterValueType,
|
||||
WorkflowExecuteMode,
|
||||
ProxyInput,
|
||||
} from './Interfaces';
|
||||
import * as NodeHelpers from './NodeHelpers';
|
||||
import { ExpressionError } from './ExpressionError';
|
||||
@@ -1067,90 +1068,87 @@ export class WorkflowDataProxy {
|
||||
);
|
||||
},
|
||||
|
||||
$input: new Proxy(
|
||||
{},
|
||||
{
|
||||
ownKeys(target) {
|
||||
return ['all', 'context', 'first', 'item', 'last', 'params'];
|
||||
},
|
||||
getOwnPropertyDescriptor(k) {
|
||||
return {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
};
|
||||
},
|
||||
get(target, property, receiver) {
|
||||
if (property === 'isProxy') return true;
|
||||
|
||||
if (property === 'item') {
|
||||
return that.connectionInputData[that.itemIndex];
|
||||
}
|
||||
if (property === 'first') {
|
||||
return (...args: unknown[]) => {
|
||||
if (args.length) {
|
||||
throw createExpressionError('$input.first() should have no arguments');
|
||||
}
|
||||
|
||||
const result = that.connectionInputData;
|
||||
if (result[0]) {
|
||||
return result[0];
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
}
|
||||
if (property === 'last') {
|
||||
return (...args: unknown[]) => {
|
||||
if (args.length) {
|
||||
throw createExpressionError('$input.last() should have no arguments');
|
||||
}
|
||||
|
||||
const result = that.connectionInputData;
|
||||
if (result.length && result[result.length - 1]) {
|
||||
return result[result.length - 1];
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
}
|
||||
if (property === 'all') {
|
||||
return () => {
|
||||
const result = that.connectionInputData;
|
||||
if (result.length) {
|
||||
return result;
|
||||
}
|
||||
return [];
|
||||
};
|
||||
}
|
||||
|
||||
if (['context', 'params'].includes(property as string)) {
|
||||
// For the following properties we need the source data so fail in case it is missing
|
||||
// for some reason (even though that should actually never happen)
|
||||
if (!that.executeData?.source) {
|
||||
throw createExpressionError('Can’t get data for expression', {
|
||||
messageTemplate: 'Can’t get data for expression under ‘%%PARAMETER%%’ field',
|
||||
functionOverrides: {
|
||||
message: 'Can’t get data',
|
||||
},
|
||||
description:
|
||||
'Apologies, this is an internal error. See details for more information',
|
||||
causeDetailed: 'Missing sourceData (probably an internal error)',
|
||||
runIndex: that.runIndex,
|
||||
});
|
||||
}
|
||||
|
||||
const sourceData: ISourceData = that.executeData.source.main[0] as ISourceData;
|
||||
|
||||
if (property === 'context') {
|
||||
return that.nodeContextGetter(sourceData.previousNode);
|
||||
}
|
||||
if (property === 'params') {
|
||||
return that.workflow.getNode(sourceData.previousNode)?.parameters;
|
||||
}
|
||||
}
|
||||
|
||||
return Reflect.get(target, property, receiver);
|
||||
},
|
||||
$input: new Proxy({} as ProxyInput, {
|
||||
ownKeys(target) {
|
||||
return ['all', 'context', 'first', 'item', 'last', 'params'];
|
||||
},
|
||||
),
|
||||
getOwnPropertyDescriptor(k) {
|
||||
return {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
};
|
||||
},
|
||||
get(target, property, receiver) {
|
||||
if (property === 'isProxy') return true;
|
||||
|
||||
if (property === 'item') {
|
||||
return that.connectionInputData[that.itemIndex];
|
||||
}
|
||||
if (property === 'first') {
|
||||
return (...args: unknown[]) => {
|
||||
if (args.length) {
|
||||
throw createExpressionError('$input.first() should have no arguments');
|
||||
}
|
||||
|
||||
const result = that.connectionInputData;
|
||||
if (result[0]) {
|
||||
return result[0];
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
}
|
||||
if (property === 'last') {
|
||||
return (...args: unknown[]) => {
|
||||
if (args.length) {
|
||||
throw createExpressionError('$input.last() should have no arguments');
|
||||
}
|
||||
|
||||
const result = that.connectionInputData;
|
||||
if (result.length && result[result.length - 1]) {
|
||||
return result[result.length - 1];
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
}
|
||||
if (property === 'all') {
|
||||
return () => {
|
||||
const result = that.connectionInputData;
|
||||
if (result.length) {
|
||||
return result;
|
||||
}
|
||||
return [];
|
||||
};
|
||||
}
|
||||
|
||||
if (['context', 'params'].includes(property as string)) {
|
||||
// For the following properties we need the source data so fail in case it is missing
|
||||
// for some reason (even though that should actually never happen)
|
||||
if (!that.executeData?.source) {
|
||||
throw createExpressionError('Can’t get data for expression', {
|
||||
messageTemplate: 'Can’t get data for expression under ‘%%PARAMETER%%’ field',
|
||||
functionOverrides: {
|
||||
message: 'Can’t get data',
|
||||
},
|
||||
description:
|
||||
'Apologies, this is an internal error. See details for more information',
|
||||
causeDetailed: 'Missing sourceData (probably an internal error)',
|
||||
runIndex: that.runIndex,
|
||||
});
|
||||
}
|
||||
|
||||
const sourceData: ISourceData = that.executeData.source.main[0] as ISourceData;
|
||||
|
||||
if (property === 'context') {
|
||||
return that.nodeContextGetter(sourceData.previousNode);
|
||||
}
|
||||
if (property === 'params') {
|
||||
return that.workflow.getNode(sourceData.previousNode)?.parameters;
|
||||
}
|
||||
}
|
||||
|
||||
return Reflect.get(target, property, receiver);
|
||||
},
|
||||
}),
|
||||
|
||||
$binary: {}, // Placeholder
|
||||
$data: {}, // Placeholder
|
||||
|
||||
Reference in New Issue
Block a user