mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 10:02:05 +00:00
✨ Add expression support to credentials
This commit is contained in:
221
packages/workflow/src/Expression.ts
Normal file
221
packages/workflow/src/Expression.ts
Normal file
@@ -0,0 +1,221 @@
|
||||
|
||||
import {
|
||||
INode,
|
||||
INodeExecutionData,
|
||||
INodeParameters,
|
||||
IRunExecutionData,
|
||||
NodeParameterValue,
|
||||
Workflow,
|
||||
WorkflowDataProxy,
|
||||
} from './';
|
||||
|
||||
// @ts-ignore
|
||||
import * as tmpl from 'riot-tmpl';
|
||||
|
||||
// Set it to use double curly brackets instead of single ones
|
||||
tmpl.brackets.set('{{ }}');
|
||||
|
||||
// Make sure that it does not always print an error when it could not resolve
|
||||
// a variable
|
||||
tmpl.tmpl.errorHandler = () => { };
|
||||
|
||||
|
||||
export class Expression {
|
||||
|
||||
workflow: Workflow;
|
||||
|
||||
constructor(workflow: Workflow) {
|
||||
this.workflow = workflow;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Converts an object to a string in a way to make it clear that
|
||||
* the value comes from an object
|
||||
*
|
||||
* @param {object} value
|
||||
* @returns {string}
|
||||
* @memberof Workflow
|
||||
*/
|
||||
convertObjectValueToString(value: object): string {
|
||||
const typeName = Array.isArray(value) ? 'Array' : 'Object';
|
||||
return `[${typeName}: ${JSON.stringify(value)}]`;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Resolves the paramter value. If it is an expression it will execute it and
|
||||
* return the result. For everything simply the supplied value will be returned.
|
||||
*
|
||||
* @param {NodeParameterValue} parameterValue
|
||||
* @param {(IRunExecutionData | null)} runExecutionData
|
||||
* @param {number} runIndex
|
||||
* @param {number} itemIndex
|
||||
* @param {string} activeNodeName
|
||||
* @param {INodeExecutionData[]} connectionInputData
|
||||
* @param {boolean} [returnObjectAsString=false]
|
||||
* @returns {(NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[])}
|
||||
* @memberof Workflow
|
||||
*/
|
||||
resolveSimpleParameterValue(parameterValue: NodeParameterValue, runExecutionData: IRunExecutionData | null, runIndex: number, itemIndex: number, activeNodeName: string, connectionInputData: INodeExecutionData[], returnObjectAsString = false): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] {
|
||||
// Check if it is an expression
|
||||
if (typeof parameterValue !== 'string' || parameterValue.charAt(0) !== '=') {
|
||||
// Is no expression so return value
|
||||
return parameterValue;
|
||||
}
|
||||
|
||||
// Is an expression
|
||||
|
||||
// Remove the equal sign
|
||||
parameterValue = parameterValue.substr(1);
|
||||
|
||||
// Generate a data proxy which allows to query workflow data
|
||||
const dataProxy = new WorkflowDataProxy(this.workflow, runExecutionData, runIndex, itemIndex, activeNodeName, connectionInputData);
|
||||
const data = dataProxy.getDataProxy();
|
||||
|
||||
// Execute the expression
|
||||
try {
|
||||
const returnValue = tmpl.tmpl(parameterValue, data);
|
||||
if (typeof returnValue === 'function') {
|
||||
throw new Error('Expression resolved to a function. Please add "()"');
|
||||
} else if (returnValue !== null && typeof returnValue === 'object') {
|
||||
if (returnObjectAsString === true) {
|
||||
return this.convertObjectValueToString(returnValue);
|
||||
}
|
||||
}
|
||||
return returnValue;
|
||||
} catch (e) {
|
||||
throw new Error(`Expression is not valid: ${e.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Resolves value of parameter. But does not work for workflow-data.
|
||||
*
|
||||
* @param {INode} node
|
||||
* @param {(string | undefined)} parameterValue
|
||||
* @param {string} [defaultValue]
|
||||
* @returns {(string | undefined)}
|
||||
* @memberof Workflow
|
||||
*/
|
||||
getSimpleParameterValue(node: INode, parameterValue: string | boolean | undefined, defaultValue?: boolean | number | string): boolean | number | string | undefined {
|
||||
if (parameterValue === undefined) {
|
||||
// Value is not set so return the default
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
// Get the value of the node (can be an expression)
|
||||
const runIndex = 0;
|
||||
const itemIndex = 0;
|
||||
const connectionInputData: INodeExecutionData[] = [];
|
||||
const runData: IRunExecutionData = {
|
||||
resultData: {
|
||||
runData: {},
|
||||
}
|
||||
};
|
||||
|
||||
return this.getParameterValue(parameterValue, runData, runIndex, itemIndex, node.name, connectionInputData) as boolean | number | string | undefined;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Resolves value of complex parameter. But does not work for workflow-data.
|
||||
*
|
||||
* @param {INode} node
|
||||
* @param {(NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[])} parameterValue
|
||||
* @param {(NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] | undefined)} [defaultValue]
|
||||
* @returns {(NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] | undefined)}
|
||||
* @memberof Workflow
|
||||
*/
|
||||
getComplexParameterValue(node: INode, parameterValue: NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[], defaultValue: NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] | undefined = undefined): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] | undefined {
|
||||
if (parameterValue === undefined) {
|
||||
// Value is not set so return the default
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
// Get the value of the node (can be an expression)
|
||||
const runIndex = 0;
|
||||
const itemIndex = 0;
|
||||
const connectionInputData: INodeExecutionData[] = [];
|
||||
const runData: IRunExecutionData = {
|
||||
resultData: {
|
||||
runData: {},
|
||||
}
|
||||
};
|
||||
|
||||
// Resolve the "outer" main values
|
||||
const returnData = this.getParameterValue(parameterValue, runData, runIndex, itemIndex, node.name, connectionInputData);
|
||||
|
||||
// Resolve the "inner" values
|
||||
return this.getParameterValue(returnData, runData, runIndex, itemIndex, node.name, connectionInputData);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the resolved node parameter value. If it is an expression it will execute it and
|
||||
* return the result. If the value to resolve is an array or object it will do the same
|
||||
* for all of the items and values.
|
||||
*
|
||||
* @param {(NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[])} parameterValue
|
||||
* @param {(IRunExecutionData | null)} runExecutionData
|
||||
* @param {number} runIndex
|
||||
* @param {number} itemIndex
|
||||
* @param {string} activeNodeName
|
||||
* @param {INodeExecutionData[]} connectionInputData
|
||||
* @param {boolean} [returnObjectAsString=false]
|
||||
* @returns {(NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[])}
|
||||
* @memberof Workflow
|
||||
*/
|
||||
getParameterValue(parameterValue: NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[], runExecutionData: IRunExecutionData | null, runIndex: number, itemIndex: number, activeNodeName: string, connectionInputData: INodeExecutionData[], returnObjectAsString = false): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] {
|
||||
// Helper function which returns true when the parameter is a complex one or array
|
||||
const isComplexParameter = (value: NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[]) => {
|
||||
return typeof value === 'object';
|
||||
};
|
||||
|
||||
// Helper function which resolves a parameter value depending on if it is simply or not
|
||||
const resolveParameterValue = (value: NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[]) => {
|
||||
if (isComplexParameter(value)) {
|
||||
return this.getParameterValue(value, runExecutionData, runIndex, itemIndex, activeNodeName, connectionInputData, returnObjectAsString);
|
||||
} else {
|
||||
return this.resolveSimpleParameterValue(value as NodeParameterValue, runExecutionData, runIndex, itemIndex, activeNodeName, connectionInputData, returnObjectAsString);
|
||||
}
|
||||
};
|
||||
|
||||
// Check if it value is a simple one that we can get it resolved directly
|
||||
if (!isComplexParameter(parameterValue)) {
|
||||
return this.resolveSimpleParameterValue(parameterValue as NodeParameterValue, runExecutionData, runIndex, itemIndex, activeNodeName, connectionInputData, returnObjectAsString);
|
||||
}
|
||||
|
||||
// The parameter value is complex so resolve depending on type
|
||||
|
||||
if (Array.isArray(parameterValue)) {
|
||||
// Data is an array
|
||||
const returnData = [];
|
||||
for (const item of parameterValue) {
|
||||
returnData.push(resolveParameterValue(item));
|
||||
}
|
||||
|
||||
if (returnObjectAsString === true && typeof returnData === 'object') {
|
||||
return this.convertObjectValueToString(returnData);
|
||||
}
|
||||
|
||||
return returnData as NodeParameterValue[] | INodeParameters[];
|
||||
} else {
|
||||
// Data is an object
|
||||
const returnData: INodeParameters = {};
|
||||
for (const key of Object.keys(parameterValue)) {
|
||||
returnData[key] = resolveParameterValue((parameterValue as INodeParameters)[key]);
|
||||
}
|
||||
|
||||
if (returnObjectAsString === true && typeof returnData === 'object') {
|
||||
return this.convertObjectValueToString(returnData);
|
||||
}
|
||||
return returnData;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -755,7 +755,7 @@ export function getNodeWebhooks(workflow: Workflow, node: INode, additionalData:
|
||||
|
||||
const returnData: IWebhookData[] = [];
|
||||
for (const webhookDescription of nodeType.description.webhooks) {
|
||||
let nodeWebhookPath = workflow.getSimpleParameterValue(node, webhookDescription['path']);
|
||||
let nodeWebhookPath = workflow.expression.getSimpleParameterValue(node, webhookDescription['path']);
|
||||
if (nodeWebhookPath === undefined) {
|
||||
// TODO: Use a proper logger
|
||||
console.error(`No webhook path could be found for node "${node.name}" in workflow "${workflowId}".`);
|
||||
@@ -768,10 +768,10 @@ export function getNodeWebhooks(workflow: Workflow, node: INode, additionalData:
|
||||
nodeWebhookPath = nodeWebhookPath.slice(1);
|
||||
}
|
||||
|
||||
const isFullPath: boolean = workflow.getSimpleParameterValue(node, webhookDescription['isFullPath'], false) as boolean;
|
||||
const isFullPath: boolean = workflow.expression.getSimpleParameterValue(node, webhookDescription['isFullPath'], false) as boolean;
|
||||
const path = getNodeWebhookPath(workflowId, node, nodeWebhookPath, isFullPath);
|
||||
|
||||
const httpMethod = workflow.getSimpleParameterValue(node, webhookDescription['httpMethod'], 'GET');
|
||||
const httpMethod = workflow.expression.getSimpleParameterValue(node, webhookDescription['httpMethod'], 'GET');
|
||||
|
||||
if (httpMethod === undefined) {
|
||||
// TODO: Use a proper logger
|
||||
@@ -809,7 +809,7 @@ export function getNodeWebhooksBasic(workflow: Workflow, node: INode): IWebhookD
|
||||
|
||||
const returnData: IWebhookData[] = [];
|
||||
for (const webhookDescription of nodeType.description.webhooks) {
|
||||
let nodeWebhookPath = workflow.getSimpleParameterValue(node, webhookDescription['path']);
|
||||
let nodeWebhookPath = workflow.expression.getSimpleParameterValue(node, webhookDescription['path']);
|
||||
if (nodeWebhookPath === undefined) {
|
||||
// TODO: Use a proper logger
|
||||
console.error(`No webhook path could be found for node "${node.name}" in workflow "${workflowId}".`);
|
||||
@@ -822,11 +822,11 @@ export function getNodeWebhooksBasic(workflow: Workflow, node: INode): IWebhookD
|
||||
nodeWebhookPath = nodeWebhookPath.slice(1);
|
||||
}
|
||||
|
||||
const isFullPath: boolean = workflow.getSimpleParameterValue(node, webhookDescription['isFullPath'], false) as boolean;
|
||||
const isFullPath: boolean = workflow.expression.getSimpleParameterValue(node, webhookDescription['isFullPath'], false) as boolean;
|
||||
|
||||
const path = getNodeWebhookPath(workflowId, node, nodeWebhookPath, isFullPath);
|
||||
|
||||
const httpMethod = workflow.getSimpleParameterValue(node, webhookDescription['httpMethod']);
|
||||
const httpMethod = workflow.expression.getSimpleParameterValue(node, webhookDescription['httpMethod']);
|
||||
|
||||
if (httpMethod === undefined) {
|
||||
// TODO: Use a proper logger
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
|
||||
import {
|
||||
Expression,
|
||||
IConnections,
|
||||
IGetExecuteTriggerFunctions,
|
||||
INode,
|
||||
@@ -23,21 +24,11 @@ import {
|
||||
NodeParameterValue,
|
||||
ObservableObject,
|
||||
WebhookSetupMethodNames,
|
||||
WorkflowDataProxy,
|
||||
WorkflowExecuteMode,
|
||||
} from './';
|
||||
|
||||
// @ts-ignore
|
||||
import * as tmpl from 'riot-tmpl';
|
||||
import { IConnection, IDataObject, IObservableObject } from './Interfaces';
|
||||
|
||||
// Set it to use double curly brackets instead of single ones
|
||||
tmpl.brackets.set('{{ }}');
|
||||
|
||||
// Make sure that it does not always print an error when it could not resolve
|
||||
// a variable
|
||||
tmpl.tmpl.errorHandler = () => { };
|
||||
|
||||
|
||||
export class Workflow {
|
||||
id: string | undefined;
|
||||
@@ -46,6 +37,7 @@ export class Workflow {
|
||||
connectionsBySourceNode: IConnections;
|
||||
connectionsByDestinationNode: IConnections;
|
||||
nodeTypes: INodeTypes;
|
||||
expression: Expression;
|
||||
active: boolean;
|
||||
settings: IWorkflowSettings;
|
||||
|
||||
@@ -90,6 +82,8 @@ export class Workflow {
|
||||
this.staticData = ObservableObject.create(parameters.staticData || {}, undefined, { ignoreEmptyOnFirstChild: true });
|
||||
|
||||
this.settings = parameters.settings || {};
|
||||
|
||||
this.expression = new Expression(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -147,21 +141,6 @@ export class Workflow {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Converts an object to a string in a way to make it clear that
|
||||
* the value comes from an object
|
||||
*
|
||||
* @param {object} value
|
||||
* @returns {string}
|
||||
* @memberof Workflow
|
||||
*/
|
||||
convertObjectValueToString(value: object): string {
|
||||
const typeName = Array.isArray(value) ? 'Array' : 'Object';
|
||||
return `[${typeName}: ${JSON.stringify(value)}]`;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A workflow can only be activated if it has a node which has either triggers
|
||||
* or webhooks defined.
|
||||
@@ -706,65 +685,6 @@ export class Workflow {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Resolves value of parameter. But does not work for workflow-data.
|
||||
*
|
||||
* @param {INode} node
|
||||
* @param {(string | undefined)} parameterValue
|
||||
* @param {string} [defaultValue]
|
||||
* @returns {(string | undefined)}
|
||||
* @memberof Workflow
|
||||
*/
|
||||
getSimpleParameterValue(node: INode, parameterValue: string | boolean | undefined, defaultValue?: boolean | number | string): boolean | number | string | undefined {
|
||||
if (parameterValue === undefined) {
|
||||
// Value is not set so return the default
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
// Get the value of the node (can be an expression)
|
||||
const runIndex = 0;
|
||||
const itemIndex = 0;
|
||||
const connectionInputData: INodeExecutionData[] = [];
|
||||
const runData: IRunExecutionData = {
|
||||
resultData: {
|
||||
runData: {},
|
||||
}
|
||||
};
|
||||
|
||||
return this.getParameterValue(parameterValue, runData, runIndex, itemIndex, node.name, connectionInputData) as boolean | number | string | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves value of complex parameter. But does not work for workflow-data.
|
||||
*
|
||||
* @param {INode} node
|
||||
* @param {(NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[])} parameterValue
|
||||
* @param {(NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] | undefined)} [defaultValue]
|
||||
* @returns {(NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] | undefined)}
|
||||
* @memberof Workflow
|
||||
*/
|
||||
getComplexParameterValue(node: INode, parameterValue: NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[], defaultValue: NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] | undefined = undefined): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] | undefined {
|
||||
if (parameterValue === undefined) {
|
||||
// Value is not set so return the default
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
// Get the value of the node (can be an expression)
|
||||
const runIndex = 0;
|
||||
const itemIndex = 0;
|
||||
const connectionInputData: INodeExecutionData[] = [];
|
||||
const runData: IRunExecutionData = {
|
||||
resultData: {
|
||||
runData: {},
|
||||
}
|
||||
};
|
||||
|
||||
// Resolve the "outer" main values
|
||||
const returnData = this.getParameterValue(parameterValue, runData, runIndex, itemIndex, node.name, connectionInputData);
|
||||
|
||||
// Resolve the "inner" values
|
||||
return this.getParameterValue(returnData, runData, runIndex, itemIndex, node.name, connectionInputData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns from which of the given nodes the workflow should get started from
|
||||
@@ -839,119 +759,6 @@ export class Workflow {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the resolved node parameter value. If it is an expression it will execute it and
|
||||
* return the result. If the value to resolve is an array or object it will do the same
|
||||
* for all of the items and values.
|
||||
*
|
||||
* @param {(NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[])} parameterValue
|
||||
* @param {(IRunExecutionData | null)} runExecutionData
|
||||
* @param {number} runIndex
|
||||
* @param {number} itemIndex
|
||||
* @param {string} activeNodeName
|
||||
* @param {INodeExecutionData[]} connectionInputData
|
||||
* @param {boolean} [returnObjectAsString=false]
|
||||
* @returns {(NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[])}
|
||||
* @memberof Workflow
|
||||
*/
|
||||
getParameterValue(parameterValue: NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[], runExecutionData: IRunExecutionData | null, runIndex: number, itemIndex: number, activeNodeName: string, connectionInputData: INodeExecutionData[], returnObjectAsString = false): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] {
|
||||
// Helper function which returns true when the parameter is a complex one or array
|
||||
const isComplexParameter = (value: NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[]) => {
|
||||
return typeof value === 'object';
|
||||
};
|
||||
|
||||
// Helper function which resolves a parameter value depending on if it is simply or not
|
||||
const resolveParameterValue = (value: NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[]) => {
|
||||
if (isComplexParameter(value)) {
|
||||
return this.getParameterValue(value, runExecutionData, runIndex, itemIndex, activeNodeName, connectionInputData, returnObjectAsString);
|
||||
} else {
|
||||
return this.resolveSimpleParameterValue(value as NodeParameterValue, runExecutionData, runIndex, itemIndex, activeNodeName, connectionInputData, returnObjectAsString);
|
||||
}
|
||||
};
|
||||
|
||||
// Check if it value is a simple one that we can get it resolved directly
|
||||
if (!isComplexParameter(parameterValue)) {
|
||||
return this.resolveSimpleParameterValue(parameterValue as NodeParameterValue, runExecutionData, runIndex, itemIndex, activeNodeName, connectionInputData, returnObjectAsString);
|
||||
}
|
||||
|
||||
// The parameter value is complex so resolve depending on type
|
||||
|
||||
if (Array.isArray(parameterValue)) {
|
||||
// Data is an array
|
||||
const returnData = [];
|
||||
for (const item of parameterValue) {
|
||||
returnData.push(resolveParameterValue(item));
|
||||
}
|
||||
|
||||
if (returnObjectAsString === true && typeof returnData === 'object') {
|
||||
return this.convertObjectValueToString(returnData);
|
||||
}
|
||||
|
||||
return returnData as NodeParameterValue[] | INodeParameters[];
|
||||
} else {
|
||||
// Data is an object
|
||||
const returnData: INodeParameters = {};
|
||||
for (const key of Object.keys(parameterValue)) {
|
||||
returnData[key] = resolveParameterValue((parameterValue as INodeParameters)[key]);
|
||||
}
|
||||
|
||||
if (returnObjectAsString === true && typeof returnData === 'object') {
|
||||
return this.convertObjectValueToString(returnData);
|
||||
}
|
||||
return returnData;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Resolves the paramter value. If it is an expression it will execute it and
|
||||
* return the result. For everything simply the supplied value will be returned.
|
||||
*
|
||||
* @param {NodeParameterValue} parameterValue
|
||||
* @param {(IRunExecutionData | null)} runExecutionData
|
||||
* @param {number} runIndex
|
||||
* @param {number} itemIndex
|
||||
* @param {string} activeNodeName
|
||||
* @param {INodeExecutionData[]} connectionInputData
|
||||
* @param {boolean} [returnObjectAsString=false]
|
||||
* @returns {(NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[])}
|
||||
* @memberof Workflow
|
||||
*/
|
||||
resolveSimpleParameterValue(parameterValue: NodeParameterValue, runExecutionData: IRunExecutionData | null, runIndex: number, itemIndex: number, activeNodeName: string, connectionInputData: INodeExecutionData[], returnObjectAsString = false): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] {
|
||||
// Check if it is an expression
|
||||
if (typeof parameterValue !== 'string' || parameterValue.charAt(0) !== '=') {
|
||||
// Is no expression so return value
|
||||
return parameterValue;
|
||||
}
|
||||
|
||||
// Is an expression
|
||||
|
||||
// Remove the equal sign
|
||||
parameterValue = parameterValue.substr(1);
|
||||
|
||||
// Generate a data proxy which allows to query workflow data
|
||||
const dataProxy = new WorkflowDataProxy(this, runExecutionData, runIndex, itemIndex, activeNodeName, connectionInputData);
|
||||
const data = dataProxy.getDataProxy();
|
||||
|
||||
// Execute the expression
|
||||
try {
|
||||
const returnValue = tmpl.tmpl(parameterValue, data);
|
||||
if (typeof returnValue === 'function') {
|
||||
throw new Error('Expression resolved to a function. Please add "()"');
|
||||
} else if (returnValue !== null && typeof returnValue === 'object') {
|
||||
if (returnObjectAsString === true) {
|
||||
return this.convertObjectValueToString(returnValue);
|
||||
}
|
||||
}
|
||||
return returnValue;
|
||||
} catch (e) {
|
||||
throw new Error(`Expression is not valid: ${e.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Executes the Webhooks method of the node
|
||||
*
|
||||
|
||||
@@ -97,7 +97,7 @@ export class WorkflowDataProxy {
|
||||
|
||||
if (typeof returnValue === 'string' && returnValue.charAt(0) === '=') {
|
||||
// The found value is an expression so resolve it
|
||||
return that.workflow.getParameterValue(returnValue, that.runExecutionData, that.runIndex, that.itemIndex, that.activeNodeName, that.connectionInputData);
|
||||
return that.workflow.expression.getParameterValue(returnValue, that.runExecutionData, that.runIndex, that.itemIndex, that.activeNodeName, that.connectionInputData);
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
@@ -337,7 +337,7 @@ export class WorkflowDataProxy {
|
||||
$env: this.envGetter(),
|
||||
$evaluateExpression: (expression: string, itemIndex?: number) => {
|
||||
itemIndex = itemIndex || that.itemIndex;
|
||||
return that.workflow.getParameterValue('=' + expression, that.runExecutionData, that.runIndex, itemIndex, that.activeNodeName, that.connectionInputData);
|
||||
return that.workflow.expression.getParameterValue('=' + expression, that.runExecutionData, that.runIndex, itemIndex, that.activeNodeName, that.connectionInputData);
|
||||
},
|
||||
$item: (itemIndex: number, runIndex?: number) => {
|
||||
const defaultReturnRunIndex = runIndex === undefined ? -1 : runIndex;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
export * from './Interfaces';
|
||||
export * from './Expression';
|
||||
export * from './Workflow';
|
||||
export * from './WorkflowDataProxy';
|
||||
export * from './WorkflowHooks';
|
||||
|
||||
@@ -1097,7 +1097,7 @@ describe('Workflow', () => {
|
||||
|
||||
for (const parameterName of Object.keys(testData.output)) {
|
||||
const parameterValue = nodes.find((node) => node.name === activeNodeName)!.parameters[parameterName];
|
||||
const result = workflow.getParameterValue(parameterValue, runExecutionData, runIndex, itemIndex, activeNodeName, connectionInputData);
|
||||
const result = workflow.expression.getParameterValue(parameterValue, runExecutionData, runIndex, itemIndex, activeNodeName, connectionInputData);
|
||||
// @ts-ignore
|
||||
expect(result).toEqual(testData.output[parameterName]);
|
||||
}
|
||||
@@ -1247,7 +1247,7 @@ describe('Workflow', () => {
|
||||
const parameterName = 'values';
|
||||
|
||||
const parameterValue = nodes.find((node) => node.name === activeNodeName)!.parameters[parameterName];
|
||||
const result = workflow.getParameterValue(parameterValue, runExecutionData, runIndex, itemIndex, activeNodeName, connectionInputData);
|
||||
const result = workflow.expression.getParameterValue(parameterValue, runExecutionData, runIndex, itemIndex, activeNodeName, connectionInputData);
|
||||
|
||||
expect(result).toEqual({
|
||||
string: [
|
||||
|
||||
Reference in New Issue
Block a user