mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 18:12:04 +00:00
fix(core): Fix node renaming in expressions
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-use-before-define */
|
||||||
/* eslint-disable no-await-in-loop */
|
/* eslint-disable no-await-in-loop */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
@@ -444,19 +445,41 @@ export class Workflow {
|
|||||||
// Reached the actual value
|
// Reached the actual value
|
||||||
if (typeof parameterValue === 'string' && parameterValue.charAt(0) === '=') {
|
if (typeof parameterValue === 'string' && parameterValue.charAt(0) === '=') {
|
||||||
// Is expression so has to be rewritten
|
// Is expression so has to be rewritten
|
||||||
|
|
||||||
// To not run the "expensive" regex stuff when it is not needed
|
// To not run the "expensive" regex stuff when it is not needed
|
||||||
// make a simple check first if it really contains the the node-name
|
// make a simple check first if it really contains the the node-name
|
||||||
if (parameterValue.includes(currentName)) {
|
if (parameterValue.includes(currentName)) {
|
||||||
// Really contains node-name (even though we do not know yet if really as $node-expression)
|
// Really contains node-name (even though we do not know yet if really as $node-expression)
|
||||||
|
|
||||||
// In case some special characters are used in name escape them
|
const escapedOldName = backslashEscape(currentName); // for match
|
||||||
const currentNameEscaped = currentName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
const escapedNewName = dollarEscape(newName); // for replacement
|
||||||
|
|
||||||
parameterValue = parameterValue.replace(
|
const setNewName = (expression: string, oldPattern: string) =>
|
||||||
new RegExp(`(\\$node(\\.|\\["|\\['))${currentNameEscaped}((\\.|"\\]|'\\]))`, 'g'),
|
expression.replace(new RegExp(oldPattern, 'g'), `$1${escapedNewName}$2`);
|
||||||
`$1${newName}$3`,
|
|
||||||
);
|
if (parameterValue.includes('$(')) {
|
||||||
|
const oldPattern = String.raw`(\$\(['"])${escapedOldName}(['"]\))`;
|
||||||
|
parameterValue = setNewName(parameterValue, oldPattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parameterValue.includes('$node[')) {
|
||||||
|
const oldPattern = String.raw`(\$node\[['"])${escapedOldName}(['"]\])`;
|
||||||
|
parameterValue = setNewName(parameterValue, oldPattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parameterValue.includes('$node.')) {
|
||||||
|
const oldPattern = String.raw`(\$node\.)${escapedOldName}(\.?)`;
|
||||||
|
parameterValue = setNewName(parameterValue, oldPattern);
|
||||||
|
|
||||||
|
if (hasDotNotationBannedChar(newName)) {
|
||||||
|
const regex = new RegExp(`.${backslashEscape(newName)}( |\\.)`, 'g');
|
||||||
|
parameterValue = parameterValue.replace(regex, `["${escapedNewName}"]$1`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parameterValue.includes('$items(')) {
|
||||||
|
const oldPattern = String.raw`(\$items\(['"])${escapedOldName}(['"],|['"]\))`;
|
||||||
|
parameterValue = setNewName(parameterValue, oldPattern);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1397,3 +1420,19 @@ export class Workflow {
|
|||||||
return { data: null };
|
return { data: null };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function hasDotNotationBannedChar(nodeName: string) {
|
||||||
|
const DOT_NOTATION_BANNED_CHARS = /^(\d)|[\\ `!@#$%^&*()_+\-=[\]{};':"\\|,.<>?~]/g;
|
||||||
|
|
||||||
|
return DOT_NOTATION_BANNED_CHARS.test(nodeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
function backslashEscape(nodeName: string) {
|
||||||
|
const BACKSLASH_ESCAPABLE_CHARS = /[.*+?^${}()|[\]\\]/g;
|
||||||
|
|
||||||
|
return nodeName.replace(BACKSLASH_ESCAPABLE_CHARS, (char) => `\\${char}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function dollarEscape(nodeName: string) {
|
||||||
|
return nodeName.replace(new RegExp('\\$', 'g'), '$$$$');
|
||||||
|
}
|
||||||
|
|||||||
@@ -66,6 +66,117 @@ describe('Workflow', () => {
|
|||||||
'={{$node["NewName"]["data"]["value2"] + \' - \' + $node["NewName"]["data"]["value2"]}}',
|
'={{$node["NewName"]["data"]["value2"] + \' - \' + $node["NewName"]["data"]["value2"]}}',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
description: 'should work with $("Node1")',
|
||||||
|
input: {
|
||||||
|
currentName: 'Node1',
|
||||||
|
newName: 'NewName',
|
||||||
|
parameters: {
|
||||||
|
value1: '={{$("Node1")["data"]["value1"] + \'Node1\'}}',
|
||||||
|
value2: '={{$("Node1")["data"]["value2"] + \' - \' + $("Node1")["data"]["value2"]}}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
value1: '={{$("NewName")["data"]["value1"] + \'Node1\'}}',
|
||||||
|
value2: '={{$("NewName")["data"]["value2"] + \' - \' + $("NewName")["data"]["value2"]}}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'should work with $items("Node1")',
|
||||||
|
input: {
|
||||||
|
currentName: 'Node1',
|
||||||
|
newName: 'NewName',
|
||||||
|
parameters: {
|
||||||
|
value1: '={{$items("Node1")["data"]["value1"] + \'Node1\'}}',
|
||||||
|
value2:
|
||||||
|
'={{$items("Node1")["data"]["value2"] + \' - \' + $items("Node1")["data"]["value2"]}}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
value1: '={{$items("NewName")["data"]["value1"] + \'Node1\'}}',
|
||||||
|
value2:
|
||||||
|
'={{$items("NewName")["data"]["value2"] + \' - \' + $items("NewName")["data"]["value2"]}}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'should work with $items("Node1", 0, 1)',
|
||||||
|
input: {
|
||||||
|
currentName: 'Node1',
|
||||||
|
newName: 'NewName',
|
||||||
|
parameters: {
|
||||||
|
value1: '={{$items("Node1", 0, 1)["data"]["value1"] + \'Node1\'}}',
|
||||||
|
value2:
|
||||||
|
'={{$items("Node1", 0, 1)["data"]["value2"] + \' - \' + $items("Node1", 0, 1)["data"]["value2"]}}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
value1: '={{$items("NewName", 0, 1)["data"]["value1"] + \'Node1\'}}',
|
||||||
|
value2:
|
||||||
|
'={{$items("NewName", 0, 1)["data"]["value2"] + \' - \' + $items("NewName", 0, 1)["data"]["value2"]}}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'should work with dot notation that contains space and special character',
|
||||||
|
input: {
|
||||||
|
currentName: 'Node1',
|
||||||
|
newName: 'New $ Name',
|
||||||
|
parameters: {
|
||||||
|
value1: "={{$node.Node1.data.value1 + 'Node1'}}",
|
||||||
|
value2: "={{$node.Node1.data.value2 + ' - ' + $node.Node1.data.value2}}",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
value1: '={{$node["New $ Name"].data.value1 + \'Node1\'}}',
|
||||||
|
value2:
|
||||||
|
'={{$node["New $ Name"].data.value2 + \' - \' + $node["New $ Name"].data.value2}}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'should work with dot notation that contains space and trailing $',
|
||||||
|
input: {
|
||||||
|
currentName: 'Node1',
|
||||||
|
newName: 'NewName$',
|
||||||
|
parameters: {
|
||||||
|
value1: "={{$node.Node1.data.value1 + 'Node1'}}",
|
||||||
|
value2: "={{$node.Node1.data.value2 + ' - ' + $node.Node1.data.value2}}",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
value1: '={{$node["NewName$"].data.value1 + \'Node1\'}}',
|
||||||
|
value2: '={{$node["NewName$"].data.value2 + \' - \' + $node["NewName$"].data.value2}}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'should work with dot notation that contains space and special character',
|
||||||
|
input: {
|
||||||
|
currentName: 'Node1',
|
||||||
|
newName: 'NewName $ $& $` $$$',
|
||||||
|
parameters: {
|
||||||
|
value1: "={{$node.Node1.data.value1 + 'Node1'}}",
|
||||||
|
value2: "={{$node.Node1.data.value2 + ' - ' + $node.Node1.data.value2}}",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
value1: '={{$node["NewName $ $& $` $$$"].data.value1 + \'Node1\'}}',
|
||||||
|
value2:
|
||||||
|
'={{$node["NewName $ $& $` $$$"].data.value2 + \' - \' + $node["NewName $ $& $` $$$"].data.value2}}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'should work with dot notation without trailing dot',
|
||||||
|
input: {
|
||||||
|
currentName: 'Node1',
|
||||||
|
newName: 'NewName',
|
||||||
|
parameters: {
|
||||||
|
value1: "={{$node.Node1 + 'Node1'}}",
|
||||||
|
value2: "={{$node.Node1 + ' - ' + $node.Node1}}",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
value1: "={{$node.NewName + 'Node1'}}",
|
||||||
|
value2: "={{$node.NewName + ' - ' + $node.NewName}}",
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
description: "should work with ['nodeName']",
|
description: "should work with ['nodeName']",
|
||||||
input: {
|
input: {
|
||||||
|
|||||||
Reference in New Issue
Block a user