Skip to content

Commit b330887

Browse files
author
drowl87
committed
refactor DynamicNode to enhance parameter evaluation and update version to 0.3.5
1 parent 6938bf1 commit b330887

File tree

2 files changed

+54
-42
lines changed

2 files changed

+54
-42
lines changed

nodes/DynamicNode/DynamicNode.node.ts

Lines changed: 53 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export class DynamicNode implements INodeType {
4040
name: 'doNotWaitToFinish',
4141
type: 'boolean',
4242
default: false,
43-
description: 'Whether to return immediately after starting the sub-workflow',
43+
description: 'Return immediately after triggering the sub-workflow. Advanced: disables result collection.',
4444
},
4545
],
4646
};
@@ -87,6 +87,32 @@ export class DynamicNode implements INodeType {
8787
? baseNode.position
8888
: [240, 0];
8989

90+
// Evaluate top-level parameters
91+
for (const key of Object.keys(nodeClone.parameters)) {
92+
const value = nodeClone.parameters[key];
93+
if (typeof value === 'string' && value.includes('{{')) {
94+
try {
95+
nodeClone.parameters[key] = await this.evaluateExpression(value, item, index);
96+
} catch (err) {
97+
this.logger.warn(`DynamicNode: Failed to evaluate parameter '${key}': ${err instanceof Error ? err.message : String(err)}`);
98+
}
99+
}
100+
}
101+
102+
// Evaluate nested body parameters
103+
const bodyParams = nodeClone.parameters?.bodyParameters?.parameters;
104+
if (Array.isArray(bodyParams)) {
105+
for (const param of bodyParams) {
106+
if (typeof param.value === 'string' && param.value.includes('{{')) {
107+
try {
108+
param.value = await this.evaluateExpression(param.value, item, index);
109+
} catch (err) {
110+
this.logger.warn(`DynamicNode: Failed to evaluate body param '${param.name}': ${err instanceof Error ? err.message : String(err)}`);
111+
}
112+
}
113+
}
114+
}
115+
90116
template.nodes.push(nodeClone);
91117
template.connections.Start.main[0][0].node = nodeClone.name;
92118

@@ -95,38 +121,28 @@ export class DynamicNode implements INodeType {
95121
const execResult = await this.executeWorkflow(
96122
{ code: template },
97123
[item],
98-
{
99-
contextData: {
100-
$data: item.json,
101-
$json: item.json,
102-
},
103-
},
124+
{},
104125
{
105126
parentExecution: {
106127
executionId: workflowProxy.$execution.id,
107128
workflowId: workflowProxy.$workflow.id,
108129
},
109-
doNotWaitToFinish: doNotWaitToFinish,
110-
itemIndex: 0,
111-
} as any,
130+
doNotWaitToFinish,
131+
},
112132
);
113133

114134
if (!doNotWaitToFinish && execResult) {
115-
if (Array.isArray(execResult)) {
116-
const flattened = execResult
117-
.flat()
118-
.filter((entry: unknown): entry is INodeExecutionData => entry !== null && typeof entry === 'object');
119-
allResults.push(...flattened);
120-
} else if (
121-
typeof execResult === 'object' &&
122-
'data' in execResult &&
123-
Array.isArray((execResult as any).data)
124-
) {
125-
const flattened = (execResult as any).data
126-
.flat()
127-
.filter((entry: unknown): entry is INodeExecutionData => entry !== null && typeof entry === 'object');
128-
allResults.push(...flattened);
129-
}
135+
const resultArray = Array.isArray(execResult)
136+
? execResult
137+
: Array.isArray((execResult as any).data)
138+
? (execResult as any).data
139+
: [];
140+
141+
allResults.push(
142+
...resultArray.flat().filter((entry: unknown): entry is INodeExecutionData =>
143+
entry !== null && typeof entry === 'object',
144+
),
145+
);
130146
}
131147
};
132148

@@ -139,7 +155,7 @@ export class DynamicNode implements INodeType {
139155
}
140156
}
141157
} else {
142-
// Run one sub-workflow with all items
158+
// One execution for all items (rare)
143159
const template = JSON.parse(JSON.stringify(subWorkflowTemplate));
144160
const nodeClone = JSON.parse(JSON.stringify(baseNode));
145161

@@ -168,21 +184,17 @@ export class DynamicNode implements INodeType {
168184
);
169185

170186
if (!doNotWaitToFinish && execResult) {
171-
if (Array.isArray(execResult)) {
172-
const flattened = execResult
173-
.flat()
174-
.filter((entry: unknown): entry is INodeExecutionData => entry !== null && typeof entry === 'object');
175-
allResults.push(...flattened);
176-
} else if (
177-
typeof execResult === 'object' &&
178-
'data' in execResult &&
179-
Array.isArray((execResult as any).data)
180-
) {
181-
const flattened = (execResult as any).data
182-
.flat()
183-
.filter((entry: unknown): entry is INodeExecutionData => entry !== null && typeof entry === 'object');
184-
allResults.push(...flattened);
185-
}
187+
const resultArray = Array.isArray(execResult)
188+
? execResult
189+
: Array.isArray((execResult as any).data)
190+
? (execResult as any).data
191+
: [];
192+
193+
allResults.push(
194+
...resultArray.flat().filter((entry: unknown): entry is INodeExecutionData =>
195+
entry !== null && typeof entry === 'object',
196+
),
197+
);
186198
}
187199
}
188200

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "n8n-nodes-dynamic-node",
3-
"version": "0.3.4",
3+
"version": "0.3.5",
44
"description": "A dynamic n8n node wrapper that can execute any node JSON by feeding it at runtime.",
55
"keywords": [
66
"n8n-community-node-package",

0 commit comments

Comments
 (0)