feat(core): Add support for pairedItem (beta) (#3012)

*  Add pairedItem support

* 👕 Fix lint issue

* 🐛 Fix resolution in frontend

* 🐛 Fix resolution issue

* 🐛 Fix resolution in frontend

* 🐛 Fix another resolution issue in frontend

*  Try to automatically add pairedItem data if possible

*  Cleanup

*  Display expression errors in editor UI

* 🐛 Fix issue that it did not display errors in production

* 🐛 Fix auto-fix of missing pairedItem data

* 🐛 Fix frontend resolution for not executed nodes

*  Fail execution on pairedItem resolve issue and display information
about itemIndex and runIndex

*  Allow that pairedItem is only set to number if runIndex is 0

*  Improve Expression Errors

*  Remove no longer needed code

*  Make errors more helpful

*  Add additional errors

* 👕 Fix lint issue

*  Add pairedItem support to core nodes

*  Improve support in Merge-Node

*  Fix issue with not correctly converted incoming pairedItem data

* 🐛 Fix frontend resolve issue

* 🐛 Fix frontend parameter name display issue

*  Improve errors

* 👕 Fix lint issue

*  Improve errors

*  Make it possible to display parameter name in error messages

*  Improve error messages

*  Fix error message

*  Improve error messages

*  Add another error message

*  Simplify
This commit is contained in:
Jan Oberhauser
2022-06-03 17:25:07 +02:00
committed by GitHub
parent 450a9aafea
commit bdb84130d6
52 changed files with 1317 additions and 152 deletions

View File

@@ -4,6 +4,8 @@ import { DateTime, Duration, Interval } from 'luxon';
// eslint-disable-next-line import/no-cycle
import {
ExpressionError,
IExecuteData,
INode,
INodeExecutionData,
INodeParameters,
@@ -21,10 +23,11 @@ import {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
tmpl.brackets.set('{{ }}');
// Make sure that it does not always print an error when it could not resolve
// a variable
// Make sure that error get forwarded
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
tmpl.tmpl.errorHandler = () => {};
tmpl.tmpl.errorHandler = (error: Error) => {
throw error;
};
export class Expression {
workflow: Workflow;
@@ -71,6 +74,7 @@ export class Expression {
mode: WorkflowExecuteMode,
timezone: string,
additionalKeys: IWorkflowDataProxyAdditionalKeys,
executeData?: IExecuteData,
returnObjectAsString = false,
selfData = {},
): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] {
@@ -98,6 +102,7 @@ export class Expression {
mode,
timezone,
additionalKeys,
executeData,
-1,
selfData,
);
@@ -148,27 +153,35 @@ export class Expression {
data.constructor = {};
// Execute the expression
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let returnValue;
try {
if (/([^a-zA-Z0-9"']window[^a-zA-Z0-9"'])/g.test(parameterValue)) {
throw new Error(`window is not allowed`);
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
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) {
return this.convertObjectValueToString(returnValue);
returnValue = tmpl.tmpl(parameterValue, data);
} catch (error) {
if (error instanceof ExpressionError) {
// Ignore all errors except if they are ExpressionErrors and they are supposed
// to fail the execution
if (error.context.failExecution) {
throw error;
}
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return returnValue;
} catch (e) {
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions, @typescript-eslint/no-unsafe-member-access
throw new Error(`Expression is not valid: ${e.message}`);
}
if (typeof returnValue === 'function') {
throw new Error('Expression resolved to a function. Please add "()"');
} else if (returnValue !== null && typeof returnValue === 'object') {
if (returnObjectAsString) {
return this.convertObjectValueToString(returnValue);
}
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return returnValue;
}
/**
@@ -186,6 +199,7 @@ export class Expression {
mode: WorkflowExecuteMode,
timezone: string,
additionalKeys: IWorkflowDataProxyAdditionalKeys,
executeData?: IExecuteData,
defaultValue?: boolean | number | string,
): boolean | number | string | undefined {
if (parameterValue === undefined) {
@@ -213,6 +227,7 @@ export class Expression {
mode,
timezone,
additionalKeys,
executeData,
) as boolean | number | string | undefined;
}
@@ -231,6 +246,7 @@ export class Expression {
mode: WorkflowExecuteMode,
timezone: string,
additionalKeys: IWorkflowDataProxyAdditionalKeys,
executeData?: IExecuteData,
defaultValue:
| NodeParameterValue
| INodeParameters
@@ -265,6 +281,7 @@ export class Expression {
mode,
timezone,
additionalKeys,
executeData,
false,
selfData,
);
@@ -280,6 +297,7 @@ export class Expression {
mode,
timezone,
additionalKeys,
executeData,
false,
selfData,
);
@@ -310,6 +328,7 @@ export class Expression {
mode: WorkflowExecuteMode,
timezone: string,
additionalKeys: IWorkflowDataProxyAdditionalKeys,
executeData?: IExecuteData,
returnObjectAsString = false,
selfData = {},
): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] {
@@ -336,6 +355,7 @@ export class Expression {
mode,
timezone,
additionalKeys,
executeData,
returnObjectAsString,
selfData,
);
@@ -351,6 +371,7 @@ export class Expression {
mode,
timezone,
additionalKeys,
executeData,
returnObjectAsString,
selfData,
);
@@ -369,6 +390,7 @@ export class Expression {
mode,
timezone,
additionalKeys,
executeData,
returnObjectAsString,
selfData,
);