mirror of
https://github.com/n8n-io/n8n.git
synced 2026-05-31 08:46:58 +02:00
72 lines
2.3 KiB
TypeScript
72 lines
2.3 KiB
TypeScript
export function hasDotNotationBannedChar(nodeName: string) {
|
|
const DOT_NOTATION_BANNED_CHARS = /^(\d)|[\\ `!@#$%^&*()_+\-=[\]{};':"\\|,.<>?~]/g;
|
|
|
|
return DOT_NOTATION_BANNED_CHARS.test(nodeName);
|
|
}
|
|
|
|
export function backslashEscape(nodeName: string) {
|
|
const BACKSLASH_ESCAPABLE_CHARS = /[.*+?^${}()|[\]\\]/g;
|
|
|
|
return nodeName.replace(BACKSLASH_ESCAPABLE_CHARS, (char) => `\\${char}`);
|
|
}
|
|
|
|
export function dollarEscape(nodeName: string) {
|
|
return nodeName.replace(new RegExp('\\$', 'g'), '$$$$');
|
|
}
|
|
|
|
type AccessPattern = {
|
|
checkPattern: string;
|
|
replacePattern: (name: string) => string;
|
|
customCallback?: (expression: string, newName: string, escapedNewName: string) => string;
|
|
};
|
|
|
|
const ACCESS_PATTERNS: AccessPattern[] = [
|
|
{
|
|
checkPattern: '$(',
|
|
replacePattern: (s) => String.raw`(\$\(['"])${s}(['"]\))`,
|
|
},
|
|
{
|
|
checkPattern: '$node[',
|
|
replacePattern: (s) => String.raw`(\$node\[['"])${s}(['"]\])`,
|
|
},
|
|
{
|
|
checkPattern: '$node.',
|
|
replacePattern: (s) => String.raw`(\$node\.)${s}(\.?)`,
|
|
customCallback: (expression: string, newName: string, escapedNewName: string) => {
|
|
if (hasDotNotationBannedChar(newName)) {
|
|
const regex = new RegExp(`.${backslashEscape(newName)}( |\\.)`, 'g');
|
|
return expression.replace(regex, `["${escapedNewName}"]$1`);
|
|
}
|
|
return expression;
|
|
},
|
|
},
|
|
{
|
|
checkPattern: '$items(',
|
|
replacePattern: (s) => String.raw`(\$items\(['"])${s}(['"],|['"]\))`,
|
|
},
|
|
];
|
|
|
|
export function applyAccessPatterns(expression: string, previousName: string, newName: string) {
|
|
// To not run the "expensive" regex stuff when it is not needed
|
|
// make a simple check first if it really contains the node-name
|
|
if (!expression.includes(previousName)) return expression;
|
|
|
|
// Really contains node-name (even though we do not know yet if really as $node-expression)
|
|
const escapedOldName = backslashEscape(previousName); // for match
|
|
const escapedNewName = dollarEscape(newName); // for replacement
|
|
|
|
for (const pattern of ACCESS_PATTERNS) {
|
|
if (expression.includes(pattern.checkPattern)) {
|
|
expression = expression.replace(
|
|
new RegExp(pattern.replacePattern(escapedOldName), 'g'),
|
|
`$1${escapedNewName}$2`,
|
|
);
|
|
|
|
if (pattern.customCallback) {
|
|
expression = pattern.customCallback(expression, newName, escapedNewName);
|
|
}
|
|
}
|
|
}
|
|
return expression;
|
|
}
|