Skip to content

Commit 9b1446e

Browse files
author
drowl87
committed
update README with detailed usage instructions and examples, improve position validation in DynamicNode, and bump version to 0.2.5
1 parent 0a4eed9 commit 9b1446e

3 files changed

Lines changed: 112 additions & 33 deletions

File tree

README.md

Lines changed: 94 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -38,51 +38,118 @@ For Docker-based deployments, add the following line before the font installatio
3838

3939
## Usage
4040

41-
1. **Wire up** Dynamic Node: connect any upstream node whose items you want to pass through.
41+
1. **Copy the node that you want to dynamically modify** by selecting it and pressing `Ctrl + C`.
42+
43+
2. **Wire up** Select `Dynamic Node` from the list of n8n nodes and wire it up to emulate your copied node.
4244

4345
2. **Switch the `Node JSON` field into *Expression* mode** (click **Fixed****Expression**).
4446

4547
3. **Paste your exported‑node JSON** into the editor. For example, a simple Graph API call:
4648

47-
```json
48-
{
49-
"parameters": {
50-
"url": "=https://graph.microsoft.com/v1.0/users/{{ $json.id_msft }}?$select=accountEnabled,userPrincipalName,id",
51-
"authentication": "genericCredentialType",
52-
"genericAuthType": "oAuth2Api",
53-
"options": {}
54-
},
55-
"type": "n8n-nodes-base.httpRequest",
56-
"typeVersion": 4.2,
57-
"position": [460, -520],
58-
"id": "fetch-enta-user-enabled-status-dynamic",
59-
"name": "Fetch Current Azure Status",
60-
"credentials": {
61-
"oAuth2Api": {
62-
"id": "{{ $json.credential_id }}",
63-
"name": "{{ $json.credential_name }}"
64-
}
65-
},
66-
"onError": "continueRegularOutput"
67-
}
68-
```
49+
- A direct paste might look like this, which the `Dynamic Node` should still be flexible enough to parse without modifying anything:
50+
```json
51+
{
52+
"nodes": [
53+
{
54+
"parameters": {
55+
"url": "=https://graph.microsoft.com/v1.0/users/{{ $json.id_msft }}?$select=accountEnabled,userPrincipalName,id",
56+
"authentication": "genericCredentialType",
57+
"genericAuthType": "oAuth2Api",
58+
"options": {}
59+
},
60+
"type": "n8n-nodes-base.httpRequest",
61+
"typeVersion": 4.2,
62+
"position": [
63+
460,
64+
-520
65+
],
66+
"id": "550e0f7c-8a0c-462d-948a-89556abe8e5b",
67+
"name": "Fetch Current Azure Status",
68+
"credentials": {
69+
"oAuth2Api": {
70+
"id": "q7iDizt7Jxoy2cKo",
71+
"name": "Microsoft Graph API Creds"
72+
}
73+
},
74+
"onError": "continueRegularOutput"
75+
}
76+
],
77+
"connections": {
78+
"Fetch Current Azure Status": {
79+
"main": [
80+
[],
81+
[]
82+
]
83+
}
84+
},
85+
"pinData": {},
86+
"meta": {
87+
"templateCredsSetupCompleted": true,
88+
"instanceId": "j91cef9ee1e9ee17cc8d16efb7974d807be5ea0cbe8d1adfceb25249ee039v76"
89+
}
90+
}
91+
```
92+
93+
- You can also clean it up if desired and flatten the array to just keep the relevant bits:
94+
```json
95+
{
96+
"parameters": {
97+
"url": "=https://graph.microsoft.com/v1.0/users/{{ $json.id_msft }}?$select=accountEnabled,userPrincipalName,id",
98+
"authentication": "genericCredentialType",
99+
"genericAuthType": "oAuth2Api",
100+
"options": {}
101+
},
102+
"type": "n8n-nodes-base.httpRequest",
103+
"typeVersion": 4.2,
104+
"position": [460, -520], //note: this line is optional and not needed to run
105+
"id": "fetch-enta-user-enabled-status-dynamic", //note: this line is optional and not needed to run
106+
"name": "Fetch Current Azure Status",
107+
"credentials": {
108+
"oAuth2Api": {
109+
"id": "{{ $json.credential_id }}",
110+
"name": "{{ $json.credential_name }}" //note: this line is optional and not needed to run
111+
}
112+
},
113+
"onError": "continueRegularOutput"
114+
}
115+
```
116+
117+
- You can also add more expressions to parameterize the other items and trim it down further to keep it clean:
118+
```json
119+
{
120+
"parameters": {
121+
"url": "{{ $json.dynamic_url }}",
122+
"authentication": "genericCredentialType",
123+
"genericAuthType": "oAuth2Api"
124+
},
125+
"type": "n8n-nodes-base.httpRequest",
126+
"typeVersion": 4.2,
127+
"name": "Fetch Current Azure Status",
128+
"credentials": {
129+
"oAuth2Api": {
130+
"id": "{{ $json.credential_id }}"
131+
}
132+
}
133+
}
134+
```
69135

70136
4. **Click *Test step***. The node will:
71137

72138
* Clone an internal **Start → YOUR NODE** mini‑workflow.
73139
* Evaluate any `{{…}}` expressions (`$json`, etc.).
74140
* Execute the underlying node with your credentials and input items.
75-
* Return its output as the Dynamic Node’s own output.
141+
* Return its output as the `Dynamic Node`’s own output.
76142

77-
> **Note:** More complex node options like pagination that rely on elements from `$response` don't seem to work since that isn't handled properly in sub-workflow/child execution contexts.
143+
> **Note:** More complex node options like pagination that rely on elements from `$response` don't seem to work since that is handled differently in sub-workflow/child execution contexts. You can still workaround that by doing a loop to manually handle pagination.
78144

79145
---
80146

81147
## Tips & Troubleshooting
82148

83-
* Always use **Expression mode** when your JSON contains `={{…}}` placeholders.
149+
* Always use **Expression mode** when your JSON contains `{{…}}` placeholders.
84150
* Ensure your pasted JSON is a **true object** (no wrapping quotes).
85-
* Double‑check that your exported node JSON includes a unique `name` field.
151+
* Double‑check that your exported node JSON includes a `name` field.
152+
* **Note:** The `Dynamic Node` will append on **" - Dynamic Node"** to whatever name you've specified to make sure there aren't name collisions with whatever node you originally copied.
86153
* If you see **“Node JSON must be an object”**, switch to Expression mode and remove stray quotes.
87154

88155
## License

nodes/DynamicNode/DynamicNode.node.ts

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export class DynamicNode implements INodeType {
3737
// 1) Pull in the incoming items
3838
const items = this.getInputData();
3939

40-
// 2) Get the userprovided node JSON (string or object)
40+
// 2) Get the user-provided node JSON (string or object)
4141
const rawParam = this.getNodeParameter('nodeJson', 0) as any;
4242
let raw: any;
4343
if (typeof rawParam === 'string') {
@@ -78,14 +78,26 @@ export class DynamicNode implements INodeType {
7878
nodeJson.name = `${nodeJson.name} - Dynamic Node`;
7979
nodeJson.id = `dynamic-${uuidv4()}`;
8080

81-
// 7) Clone the sub-workflow template
81+
// —— DEFAULT POSITION ——
82+
// 7) Ensure a valid position array
83+
if (
84+
!nodeJson.position ||
85+
!Array.isArray(nodeJson.position) ||
86+
nodeJson.position.length !== 2 ||
87+
typeof nodeJson.position[0] !== 'number' ||
88+
typeof nodeJson.position[1] !== 'number'
89+
) {
90+
nodeJson.position = [240, 0];
91+
}
92+
93+
// 8) Clone the sub-workflow template
8294
const template = JSON.parse(JSON.stringify(subWorkflowTemplate)) as any;
8395

84-
// 8) Inject & wire
96+
// 9) Inject & wire
8597
template.nodes.push(nodeJson);
8698
template.connections.Start.main[0][0].node = nodeJson.name;
8799

88-
// 9) Execute the mini-workflow to completion
100+
// 10) Execute the mini-workflow to completion
89101
const workflowProxy = this.getWorkflowDataProxy(0);
90102
const executionResult: any = await this.executeWorkflow(
91103
{ code: template },
@@ -100,7 +112,7 @@ export class DynamicNode implements INodeType {
100112
},
101113
);
102114

103-
// 10) Grab and return the data
115+
// 11) Grab and return the data
104116
const returnedData = Array.isArray(executionResult)
105117
? executionResult
106118
: (executionResult as any).data as INodeExecutionData[][];

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.2.4",
3+
"version": "0.2.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)