mirror of
https://github.com/czlonkowski/n8n-mcp.git
synced 2026-04-02 15:43:07 +00:00
fix: validation bugs — If/Switch version check, Set false positive, bare expressions (#675, #676, #677) (#678)
- #675: Wire `validateConditionNodeStructure` into `WorkflowValidator` with version-conditional checks (If v2.2+ requires options, v2.0-2.1 validates operators, v1.x skipped; Switch v3.2+ requires options) - #676: Fix `validateSet` to check `assignments.assignments` (v3+) alongside `config.values` (v1/v2), eliminating false positive warnings - #677: Add anchored heuristic pre-pass in `ExpressionValidator` detecting bare `$json`, `$node`, `$input`, `$execution`, `$workflow`, `$prevNode`, `$env`, `$now`, `$today`, `$itemIndex`, `$runIndex` references missing `={{ }}` 25 new tests across 3 test files. Conceived by Romuald Członkowski - https://www.aiadvisors.pl/en Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
committed by
GitHub
parent
6e4a9d520d
commit
20ebfbb0fc
@@ -19,6 +19,18 @@ interface ExpressionContext {
|
||||
}
|
||||
|
||||
export class ExpressionValidator {
|
||||
// Bare n8n variable references missing {{ }} wrappers
|
||||
private static readonly BARE_EXPRESSION_PATTERNS: Array<{ pattern: RegExp; name: string }> = [
|
||||
{ pattern: /^\$json[.\[]/, name: '$json' },
|
||||
{ pattern: /^\$node\[/, name: '$node' },
|
||||
{ pattern: /^\$input\./, name: '$input' },
|
||||
{ pattern: /^\$execution\./, name: '$execution' },
|
||||
{ pattern: /^\$workflow\./, name: '$workflow' },
|
||||
{ pattern: /^\$prevNode\./, name: '$prevNode' },
|
||||
{ pattern: /^\$env\./, name: '$env' },
|
||||
{ pattern: /^\$(now|today|itemIndex|runIndex)$/, name: 'built-in variable' },
|
||||
];
|
||||
|
||||
// Common n8n expression patterns
|
||||
private static readonly EXPRESSION_PATTERN = /\{\{([\s\S]+?)\}\}/g;
|
||||
private static readonly VARIABLE_PATTERNS = {
|
||||
@@ -288,6 +300,32 @@ export class ExpressionValidator {
|
||||
return combinedResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect bare n8n variable references missing {{ }} wrappers.
|
||||
* Emits warnings since the value is technically valid as a literal string.
|
||||
*/
|
||||
private static checkBareExpression(
|
||||
value: string,
|
||||
path: string,
|
||||
result: ExpressionValidationResult
|
||||
): void {
|
||||
if (value.includes('{{') || value.startsWith('=')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const trimmed = value.trim();
|
||||
for (const { pattern, name } of this.BARE_EXPRESSION_PATTERNS) {
|
||||
if (pattern.test(trimmed)) {
|
||||
result.warnings.push(
|
||||
(path ? `${path}: ` : '') +
|
||||
`Possible unwrapped expression: "${trimmed}" looks like an n8n ${name} reference. ` +
|
||||
`Use "={{ ${trimmed} }}" to evaluate it as an expression.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively validate expressions in parameters
|
||||
*/
|
||||
@@ -307,6 +345,9 @@ export class ExpressionValidator {
|
||||
}
|
||||
|
||||
if (typeof obj === 'string') {
|
||||
// Detect bare expressions missing {{ }} wrappers
|
||||
this.checkBareExpression(obj, path, result);
|
||||
|
||||
if (obj.includes('{{')) {
|
||||
const validation = this.validateExpression(obj, context);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user