Skip to content

Commit

Permalink
fix(core): Fix node renaming in expressions
Browse files Browse the repository at this point in the history
  • Loading branch information
michael-radency authored Sep 13, 2022
1 parent 8c95d6e commit 381c09f
Show file tree
Hide file tree
Showing 2 changed files with 157 additions and 7 deletions.
53 changes: 46 additions & 7 deletions packages/workflow/src/Workflow.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-use-before-define */
/* eslint-disable no-await-in-loop */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
Expand Down Expand Up @@ -444,19 +445,41 @@ export class Workflow {
// Reached the actual value
if (typeof parameterValue === 'string' && parameterValue.charAt(0) === '=') {
// Is expression so has to be rewritten

// 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
if (parameterValue.includes(currentName)) {
// 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 currentNameEscaped = currentName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
const escapedOldName = backslashEscape(currentName); // for match
const escapedNewName = dollarEscape(newName); // for replacement

const setNewName = (expression: string, oldPattern: string) =>
expression.replace(new RegExp(oldPattern, 'g'), `$1${escapedNewName}$2`);

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`);
}
}

parameterValue = parameterValue.replace(
new RegExp(`(\\$node(\\.|\\["|\\['))${currentNameEscaped}((\\.|"\\]|'\\]))`, 'g'),
`$1${newName}$3`,
);
if (parameterValue.includes('$items(')) {
const oldPattern = String.raw`(\$items\(['"])${escapedOldName}(['"],|['"]\))`;
parameterValue = setNewName(parameterValue, oldPattern);
}
}
}

Expand Down Expand Up @@ -1397,3 +1420,19 @@ export class Workflow {
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'), '$$$$');
}
111 changes: 111 additions & 0 deletions packages/workflow/test/Workflow.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,117 @@ describe('Workflow', () => {
'={{$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']",
input: {
Expand Down

0 comments on commit 381c09f

Please sign in to comment.