bps-kit 1.2.2 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.bps-kit.json +4 -4
- package/README.md +3 -0
- package/implementation_plan.md.resolved +37 -0
- package/package.json +2 -2
- package/templates/agents-template/ARCHITECTURE.md +21 -9
- package/templates/agents-template/agents/automation-specialist.md +157 -0
- package/templates/agents-template/rules/GEMINI.md +2 -10
- package/templates/agents-template/workflows/automate.md +153 -0
- package/templates/skills_normal/n8n-code-javascript/BUILTIN_FUNCTIONS.md +764 -0
- package/templates/skills_normal/n8n-code-javascript/COMMON_PATTERNS.md +1110 -0
- package/templates/skills_normal/n8n-code-javascript/DATA_ACCESS.md +782 -0
- package/templates/skills_normal/n8n-code-javascript/ERROR_PATTERNS.md +763 -0
- package/templates/skills_normal/n8n-code-javascript/README.md +350 -0
- package/templates/skills_normal/n8n-code-javascript/SKILL.md +699 -0
- package/templates/skills_normal/n8n-code-python/COMMON_PATTERNS.md +794 -0
- package/templates/skills_normal/n8n-code-python/DATA_ACCESS.md +702 -0
- package/templates/skills_normal/n8n-code-python/ERROR_PATTERNS.md +601 -0
- package/templates/skills_normal/n8n-code-python/README.md +386 -0
- package/templates/skills_normal/n8n-code-python/SKILL.md +748 -0
- package/templates/skills_normal/n8n-code-python/STANDARD_LIBRARY.md +974 -0
- package/templates/skills_normal/n8n-expression-syntax/COMMON_MISTAKES.md +393 -0
- package/templates/skills_normal/n8n-expression-syntax/EXAMPLES.md +483 -0
- package/templates/skills_normal/n8n-expression-syntax/README.md +93 -0
- package/templates/skills_normal/n8n-expression-syntax/SKILL.md +516 -0
- package/templates/skills_normal/n8n-mcp-tools-expert/README.md +99 -0
- package/templates/skills_normal/n8n-mcp-tools-expert/SEARCH_GUIDE.md +374 -0
- package/templates/skills_normal/n8n-mcp-tools-expert/SKILL.md +642 -0
- package/templates/skills_normal/n8n-mcp-tools-expert/VALIDATION_GUIDE.md +442 -0
- package/templates/skills_normal/n8n-mcp-tools-expert/WORKFLOW_GUIDE.md +618 -0
- package/templates/skills_normal/n8n-node-configuration/DEPENDENCIES.md +789 -0
- package/templates/skills_normal/n8n-node-configuration/OPERATION_PATTERNS.md +913 -0
- package/templates/skills_normal/n8n-node-configuration/README.md +364 -0
- package/templates/skills_normal/n8n-node-configuration/SKILL.md +785 -0
- package/templates/skills_normal/n8n-validation-expert/ERROR_CATALOG.md +943 -0
- package/templates/skills_normal/n8n-validation-expert/FALSE_POSITIVES.md +720 -0
- package/templates/skills_normal/n8n-validation-expert/README.md +290 -0
- package/templates/skills_normal/n8n-validation-expert/SKILL.md +689 -0
- package/templates/skills_normal/n8n-workflow-patterns/README.md +251 -0
- package/templates/skills_normal/n8n-workflow-patterns/SKILL.md +411 -0
- package/templates/skills_normal/n8n-workflow-patterns/ai_agent_workflow.md +784 -0
- package/templates/skills_normal/n8n-workflow-patterns/database_operations.md +785 -0
- package/templates/skills_normal/n8n-workflow-patterns/http_api_integration.md +734 -0
- package/templates/skills_normal/n8n-workflow-patterns/scheduled_tasks.md +773 -0
- package/templates/skills_normal/n8n-workflow-patterns/webhook_processing.md +545 -0
- package/templates/vault/n8n-code-javascript/SKILL.md +10 -10
- package/templates/vault/n8n-code-python/SKILL.md +11 -11
- package/templates/vault/n8n-expression-syntax/SKILL.md +4 -4
- package/templates/vault/n8n-mcp-tools-expert/SKILL.md +9 -9
- package/templates/vault/n8n-node-configuration/SKILL.md +2 -2
- package/templates/vault/n8n-validation-expert/SKILL.md +3 -3
- package/templates/vault/n8n-workflow-patterns/SKILL.md +11 -11
|
@@ -0,0 +1,913 @@
|
|
|
1
|
+
# Operation Patterns Guide
|
|
2
|
+
|
|
3
|
+
Common node configuration patterns organized by node type and operation.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
**Purpose**: Quick reference for common node configurations
|
|
10
|
+
|
|
11
|
+
**Coverage**: Top 20 most-used nodes from 525 available
|
|
12
|
+
|
|
13
|
+
**Pattern format**:
|
|
14
|
+
- Minimal valid configuration
|
|
15
|
+
- Common options
|
|
16
|
+
- Real-world examples
|
|
17
|
+
- Gotchas and tips
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## HTTP & API Nodes
|
|
22
|
+
|
|
23
|
+
### HTTP Request (nodes-base.httpRequest)
|
|
24
|
+
|
|
25
|
+
Most versatile node for HTTP operations
|
|
26
|
+
|
|
27
|
+
#### GET Request
|
|
28
|
+
|
|
29
|
+
**Minimal**:
|
|
30
|
+
```javascript
|
|
31
|
+
{
|
|
32
|
+
"method": "GET",
|
|
33
|
+
"url": "https://api.example.com/users",
|
|
34
|
+
"authentication": "none"
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
**With query parameters**:
|
|
39
|
+
```javascript
|
|
40
|
+
{
|
|
41
|
+
"method": "GET",
|
|
42
|
+
"url": "https://api.example.com/users",
|
|
43
|
+
"authentication": "none",
|
|
44
|
+
"sendQuery": true,
|
|
45
|
+
"queryParameters": {
|
|
46
|
+
"parameters": [
|
|
47
|
+
{
|
|
48
|
+
"name": "limit",
|
|
49
|
+
"value": "100"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"name": "offset",
|
|
53
|
+
"value": "={{$json.offset}}"
|
|
54
|
+
}
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**With authentication**:
|
|
61
|
+
```javascript
|
|
62
|
+
{
|
|
63
|
+
"method": "GET",
|
|
64
|
+
"url": "https://api.example.com/users",
|
|
65
|
+
"authentication": "predefinedCredentialType",
|
|
66
|
+
"nodeCredentialType": "httpHeaderAuth"
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
#### POST with JSON
|
|
71
|
+
|
|
72
|
+
**Minimal**:
|
|
73
|
+
```javascript
|
|
74
|
+
{
|
|
75
|
+
"method": "POST",
|
|
76
|
+
"url": "https://api.example.com/users",
|
|
77
|
+
"authentication": "none",
|
|
78
|
+
"sendBody": true,
|
|
79
|
+
"body": {
|
|
80
|
+
"contentType": "json",
|
|
81
|
+
"content": {
|
|
82
|
+
"name": "John Doe",
|
|
83
|
+
"email": "john@example.com"
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**With expressions**:
|
|
90
|
+
```javascript
|
|
91
|
+
{
|
|
92
|
+
"method": "POST",
|
|
93
|
+
"url": "https://api.example.com/users",
|
|
94
|
+
"authentication": "none",
|
|
95
|
+
"sendBody": true,
|
|
96
|
+
"body": {
|
|
97
|
+
"contentType": "json",
|
|
98
|
+
"content": {
|
|
99
|
+
"name": "={{$json.name}}",
|
|
100
|
+
"email": "={{$json.email}}",
|
|
101
|
+
"metadata": {
|
|
102
|
+
"source": "n8n",
|
|
103
|
+
"timestamp": "={{$now.toISO()}}"
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**Gotcha**: Remember `sendBody: true` for POST/PUT/PATCH!
|
|
111
|
+
|
|
112
|
+
#### PUT/PATCH Request
|
|
113
|
+
|
|
114
|
+
**Pattern**: Same as POST, but method changes
|
|
115
|
+
```javascript
|
|
116
|
+
{
|
|
117
|
+
"method": "PUT", // or "PATCH"
|
|
118
|
+
"url": "https://api.example.com/users/123",
|
|
119
|
+
"authentication": "none",
|
|
120
|
+
"sendBody": true,
|
|
121
|
+
"body": {
|
|
122
|
+
"contentType": "json",
|
|
123
|
+
"content": {
|
|
124
|
+
"name": "Updated Name"
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
#### DELETE Request
|
|
131
|
+
|
|
132
|
+
**Minimal** (no body):
|
|
133
|
+
```javascript
|
|
134
|
+
{
|
|
135
|
+
"method": "DELETE",
|
|
136
|
+
"url": "https://api.example.com/users/123",
|
|
137
|
+
"authentication": "none"
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**With body** (some APIs allow):
|
|
142
|
+
```javascript
|
|
143
|
+
{
|
|
144
|
+
"method": "DELETE",
|
|
145
|
+
"url": "https://api.example.com/users",
|
|
146
|
+
"authentication": "none",
|
|
147
|
+
"sendBody": true,
|
|
148
|
+
"body": {
|
|
149
|
+
"contentType": "json",
|
|
150
|
+
"content": {
|
|
151
|
+
"ids": ["123", "456"]
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
### Webhook (nodes-base.webhook)
|
|
160
|
+
|
|
161
|
+
Most common trigger - 813 searches!
|
|
162
|
+
|
|
163
|
+
#### Basic Webhook
|
|
164
|
+
|
|
165
|
+
**Minimal**:
|
|
166
|
+
```javascript
|
|
167
|
+
{
|
|
168
|
+
"path": "my-webhook",
|
|
169
|
+
"httpMethod": "POST",
|
|
170
|
+
"responseMode": "onReceived"
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
**Gotcha**: Webhook data is under `$json.body`, not `$json`!
|
|
175
|
+
|
|
176
|
+
```javascript
|
|
177
|
+
// ❌ Wrong
|
|
178
|
+
{
|
|
179
|
+
"text": "={{$json.email}}"
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// ✅ Correct
|
|
183
|
+
{
|
|
184
|
+
"text": "={{$json.body.email}}"
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
#### Webhook with Authentication
|
|
189
|
+
|
|
190
|
+
**Header auth**:
|
|
191
|
+
```javascript
|
|
192
|
+
{
|
|
193
|
+
"path": "secure-webhook",
|
|
194
|
+
"httpMethod": "POST",
|
|
195
|
+
"responseMode": "onReceived",
|
|
196
|
+
"authentication": "headerAuth",
|
|
197
|
+
"options": {
|
|
198
|
+
"responseCode": 200,
|
|
199
|
+
"responseData": "{\n \"success\": true\n}"
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
#### Webhook Returning Data
|
|
205
|
+
|
|
206
|
+
**Custom response**:
|
|
207
|
+
```javascript
|
|
208
|
+
{
|
|
209
|
+
"path": "my-webhook",
|
|
210
|
+
"httpMethod": "POST",
|
|
211
|
+
"responseMode": "lastNode", // Return data from last node
|
|
212
|
+
"options": {
|
|
213
|
+
"responseCode": 201,
|
|
214
|
+
"responseHeaders": {
|
|
215
|
+
"entries": [
|
|
216
|
+
{
|
|
217
|
+
"name": "Content-Type",
|
|
218
|
+
"value": "application/json"
|
|
219
|
+
}
|
|
220
|
+
]
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## Communication Nodes
|
|
229
|
+
|
|
230
|
+
### Slack (nodes-base.slack)
|
|
231
|
+
|
|
232
|
+
Popular choice for AI agent workflows
|
|
233
|
+
|
|
234
|
+
#### Post Message
|
|
235
|
+
|
|
236
|
+
**Minimal**:
|
|
237
|
+
```javascript
|
|
238
|
+
{
|
|
239
|
+
"resource": "message",
|
|
240
|
+
"operation": "post",
|
|
241
|
+
"channel": "#general",
|
|
242
|
+
"text": "Hello from n8n!"
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
**With dynamic content**:
|
|
247
|
+
```javascript
|
|
248
|
+
{
|
|
249
|
+
"resource": "message",
|
|
250
|
+
"operation": "post",
|
|
251
|
+
"channel": "={{$json.channel}}",
|
|
252
|
+
"text": "New user: {{$json.name}} ({{$json.email}})"
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
**With attachments**:
|
|
257
|
+
```javascript
|
|
258
|
+
{
|
|
259
|
+
"resource": "message",
|
|
260
|
+
"operation": "post",
|
|
261
|
+
"channel": "#alerts",
|
|
262
|
+
"text": "Error Alert",
|
|
263
|
+
"attachments": [
|
|
264
|
+
{
|
|
265
|
+
"color": "#ff0000",
|
|
266
|
+
"fields": [
|
|
267
|
+
{
|
|
268
|
+
"title": "Error Type",
|
|
269
|
+
"value": "={{$json.errorType}}"
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
"title": "Timestamp",
|
|
273
|
+
"value": "={{$now.toLocaleString()}}"
|
|
274
|
+
}
|
|
275
|
+
]
|
|
276
|
+
}
|
|
277
|
+
]
|
|
278
|
+
}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
**Gotcha**: Channel must start with `#` for public channels or be a channel ID!
|
|
282
|
+
|
|
283
|
+
#### Update Message
|
|
284
|
+
|
|
285
|
+
**Minimal**:
|
|
286
|
+
```javascript
|
|
287
|
+
{
|
|
288
|
+
"resource": "message",
|
|
289
|
+
"operation": "update",
|
|
290
|
+
"messageId": "1234567890.123456", // From previous message post
|
|
291
|
+
"text": "Updated message content"
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
**Note**: `messageId` required, `channel` optional (can be inferred)
|
|
296
|
+
|
|
297
|
+
#### Create Channel
|
|
298
|
+
|
|
299
|
+
**Minimal**:
|
|
300
|
+
```javascript
|
|
301
|
+
{
|
|
302
|
+
"resource": "channel",
|
|
303
|
+
"operation": "create",
|
|
304
|
+
"name": "new-project-channel", // Lowercase, no spaces
|
|
305
|
+
"isPrivate": false
|
|
306
|
+
}
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
**Gotcha**: Channel name must be lowercase, no spaces, 1-80 chars!
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
313
|
+
### Gmail (nodes-base.gmail)
|
|
314
|
+
|
|
315
|
+
Popular for email automation
|
|
316
|
+
|
|
317
|
+
#### Send Email
|
|
318
|
+
|
|
319
|
+
**Minimal**:
|
|
320
|
+
```javascript
|
|
321
|
+
{
|
|
322
|
+
"resource": "message",
|
|
323
|
+
"operation": "send",
|
|
324
|
+
"to": "user@example.com",
|
|
325
|
+
"subject": "Hello from n8n",
|
|
326
|
+
"message": "This is the email body"
|
|
327
|
+
}
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
**With dynamic content**:
|
|
331
|
+
```javascript
|
|
332
|
+
{
|
|
333
|
+
"resource": "message",
|
|
334
|
+
"operation": "send",
|
|
335
|
+
"to": "={{$json.email}}",
|
|
336
|
+
"subject": "Order Confirmation #{{$json.orderId}}",
|
|
337
|
+
"message": "Dear {{$json.name}},\n\nYour order has been confirmed.\n\nThank you!",
|
|
338
|
+
"options": {
|
|
339
|
+
"ccList": "admin@example.com",
|
|
340
|
+
"replyTo": "support@example.com"
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
#### Get Email
|
|
346
|
+
|
|
347
|
+
**Minimal**:
|
|
348
|
+
```javascript
|
|
349
|
+
{
|
|
350
|
+
"resource": "message",
|
|
351
|
+
"operation": "getAll",
|
|
352
|
+
"returnAll": false,
|
|
353
|
+
"limit": 10
|
|
354
|
+
}
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
**With filters**:
|
|
358
|
+
```javascript
|
|
359
|
+
{
|
|
360
|
+
"resource": "message",
|
|
361
|
+
"operation": "getAll",
|
|
362
|
+
"returnAll": false,
|
|
363
|
+
"limit": 50,
|
|
364
|
+
"filters": {
|
|
365
|
+
"q": "is:unread from:important@example.com",
|
|
366
|
+
"labelIds": ["INBOX"]
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
---
|
|
372
|
+
|
|
373
|
+
## Database Nodes
|
|
374
|
+
|
|
375
|
+
### Postgres (nodes-base.postgres)
|
|
376
|
+
|
|
377
|
+
Database operations - 456 templates
|
|
378
|
+
|
|
379
|
+
#### Execute Query
|
|
380
|
+
|
|
381
|
+
**Minimal** (SELECT):
|
|
382
|
+
```javascript
|
|
383
|
+
{
|
|
384
|
+
"operation": "executeQuery",
|
|
385
|
+
"query": "SELECT * FROM users WHERE active = true LIMIT 100"
|
|
386
|
+
}
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
**With parameters** (SQL injection prevention):
|
|
390
|
+
```javascript
|
|
391
|
+
{
|
|
392
|
+
"operation": "executeQuery",
|
|
393
|
+
"query": "SELECT * FROM users WHERE email = $1 AND active = $2",
|
|
394
|
+
"additionalFields": {
|
|
395
|
+
"mode": "list",
|
|
396
|
+
"queryParameters": "user@example.com,true"
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
**Gotcha**: ALWAYS use parameterized queries for user input!
|
|
402
|
+
|
|
403
|
+
```javascript
|
|
404
|
+
// ❌ BAD - SQL injection risk!
|
|
405
|
+
{
|
|
406
|
+
"query": "SELECT * FROM users WHERE email = '{{$json.email}}'"
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// ✅ GOOD - Parameterized
|
|
410
|
+
{
|
|
411
|
+
"query": "SELECT * FROM users WHERE email = $1",
|
|
412
|
+
"additionalFields": {
|
|
413
|
+
"mode": "list",
|
|
414
|
+
"queryParameters": "={{$json.email}}"
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
#### Insert
|
|
420
|
+
|
|
421
|
+
**Minimal**:
|
|
422
|
+
```javascript
|
|
423
|
+
{
|
|
424
|
+
"operation": "insert",
|
|
425
|
+
"table": "users",
|
|
426
|
+
"columns": "name,email,created_at",
|
|
427
|
+
"additionalFields": {
|
|
428
|
+
"mode": "list",
|
|
429
|
+
"queryParameters": "John Doe,john@example.com,NOW()"
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
**With expressions**:
|
|
435
|
+
```javascript
|
|
436
|
+
{
|
|
437
|
+
"operation": "insert",
|
|
438
|
+
"table": "users",
|
|
439
|
+
"columns": "name,email,metadata",
|
|
440
|
+
"additionalFields": {
|
|
441
|
+
"mode": "list",
|
|
442
|
+
"queryParameters": "={{$json.name}},={{$json.email}},{{JSON.stringify($json)}}"
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
#### Update
|
|
448
|
+
|
|
449
|
+
**Minimal**:
|
|
450
|
+
```javascript
|
|
451
|
+
{
|
|
452
|
+
"operation": "update",
|
|
453
|
+
"table": "users",
|
|
454
|
+
"updateKey": "id",
|
|
455
|
+
"columns": "name,email",
|
|
456
|
+
"additionalFields": {
|
|
457
|
+
"mode": "list",
|
|
458
|
+
"queryParameters": "={{$json.id}},Updated Name,newemail@example.com"
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
---
|
|
464
|
+
|
|
465
|
+
## Data Transformation Nodes
|
|
466
|
+
|
|
467
|
+
### Set (nodes-base.set)
|
|
468
|
+
|
|
469
|
+
Most used transformation - 68% of workflows!
|
|
470
|
+
|
|
471
|
+
#### Set Fixed Values
|
|
472
|
+
|
|
473
|
+
**Minimal**:
|
|
474
|
+
```javascript
|
|
475
|
+
{
|
|
476
|
+
"mode": "manual",
|
|
477
|
+
"duplicateItem": false,
|
|
478
|
+
"assignments": {
|
|
479
|
+
"assignments": [
|
|
480
|
+
{
|
|
481
|
+
"name": "status",
|
|
482
|
+
"value": "active",
|
|
483
|
+
"type": "string"
|
|
484
|
+
},
|
|
485
|
+
{
|
|
486
|
+
"name": "count",
|
|
487
|
+
"value": 100,
|
|
488
|
+
"type": "number"
|
|
489
|
+
}
|
|
490
|
+
]
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
#### Set from Input Data
|
|
496
|
+
|
|
497
|
+
**Mapping data**:
|
|
498
|
+
```javascript
|
|
499
|
+
{
|
|
500
|
+
"mode": "manual",
|
|
501
|
+
"duplicateItem": false,
|
|
502
|
+
"assignments": {
|
|
503
|
+
"assignments": [
|
|
504
|
+
{
|
|
505
|
+
"name": "fullName",
|
|
506
|
+
"value": "={{$json.firstName}} {{$json.lastName}}",
|
|
507
|
+
"type": "string"
|
|
508
|
+
},
|
|
509
|
+
{
|
|
510
|
+
"name": "email",
|
|
511
|
+
"value": "={{$json.email.toLowerCase()}}",
|
|
512
|
+
"type": "string"
|
|
513
|
+
},
|
|
514
|
+
{
|
|
515
|
+
"name": "timestamp",
|
|
516
|
+
"value": "={{$now.toISO()}}",
|
|
517
|
+
"type": "string"
|
|
518
|
+
}
|
|
519
|
+
]
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
**Gotcha**: Use correct `type` for each field!
|
|
525
|
+
|
|
526
|
+
```javascript
|
|
527
|
+
// ❌ Wrong type
|
|
528
|
+
{
|
|
529
|
+
"name": "age",
|
|
530
|
+
"value": "25", // String
|
|
531
|
+
"type": "string" // Will be string "25"
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
// ✅ Correct type
|
|
535
|
+
{
|
|
536
|
+
"name": "age",
|
|
537
|
+
"value": 25, // Number
|
|
538
|
+
"type": "number" // Will be number 25
|
|
539
|
+
}
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
---
|
|
543
|
+
|
|
544
|
+
### Code (nodes-base.code)
|
|
545
|
+
|
|
546
|
+
JavaScript execution - 42% of workflows
|
|
547
|
+
|
|
548
|
+
#### Simple Transformation
|
|
549
|
+
|
|
550
|
+
**Minimal**:
|
|
551
|
+
```javascript
|
|
552
|
+
{
|
|
553
|
+
"mode": "runOnceForAllItems",
|
|
554
|
+
"jsCode": "return $input.all().map(item => ({\n json: {\n name: item.json.name.toUpperCase(),\n email: item.json.email\n }\n}));"
|
|
555
|
+
}
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
**Per-item processing**:
|
|
559
|
+
```javascript
|
|
560
|
+
{
|
|
561
|
+
"mode": "runOnceForEachItem",
|
|
562
|
+
"jsCode": "// Process each item\nconst data = $input.item.json;\n\nreturn {\n json: {\n fullName: `${data.firstName} ${data.lastName}`,\n email: data.email.toLowerCase(),\n timestamp: new Date().toISOString()\n }\n};"
|
|
563
|
+
}
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
**Gotcha**: In Code nodes, use `$input.item.json` or `$input.all()`, NOT `{{...}}`!
|
|
567
|
+
|
|
568
|
+
```javascript
|
|
569
|
+
// ❌ Wrong - expressions don't work in Code nodes
|
|
570
|
+
{
|
|
571
|
+
"jsCode": "const name = '={{$json.name}}';"
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
// ✅ Correct - direct access
|
|
575
|
+
{
|
|
576
|
+
"jsCode": "const name = $input.item.json.name;"
|
|
577
|
+
}
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
---
|
|
581
|
+
|
|
582
|
+
## Conditional Nodes
|
|
583
|
+
|
|
584
|
+
### IF (nodes-base.if)
|
|
585
|
+
|
|
586
|
+
Conditional logic - 38% of workflows
|
|
587
|
+
|
|
588
|
+
#### String Comparison
|
|
589
|
+
|
|
590
|
+
**Equals** (binary):
|
|
591
|
+
```javascript
|
|
592
|
+
{
|
|
593
|
+
"conditions": {
|
|
594
|
+
"string": [
|
|
595
|
+
{
|
|
596
|
+
"value1": "={{$json.status}}",
|
|
597
|
+
"operation": "equals",
|
|
598
|
+
"value2": "active"
|
|
599
|
+
}
|
|
600
|
+
]
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
**Contains** (binary):
|
|
606
|
+
```javascript
|
|
607
|
+
{
|
|
608
|
+
"conditions": {
|
|
609
|
+
"string": [
|
|
610
|
+
{
|
|
611
|
+
"value1": "={{$json.email}}",
|
|
612
|
+
"operation": "contains",
|
|
613
|
+
"value2": "@example.com"
|
|
614
|
+
}
|
|
615
|
+
]
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
```
|
|
619
|
+
|
|
620
|
+
**isEmpty** (unary):
|
|
621
|
+
```javascript
|
|
622
|
+
{
|
|
623
|
+
"conditions": {
|
|
624
|
+
"string": [
|
|
625
|
+
{
|
|
626
|
+
"value1": "={{$json.email}}",
|
|
627
|
+
"operation": "isEmpty"
|
|
628
|
+
// No value2 - unary operator
|
|
629
|
+
// singleValue: true added by auto-sanitization
|
|
630
|
+
}
|
|
631
|
+
]
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
```
|
|
635
|
+
|
|
636
|
+
**Gotcha**: Unary operators (isEmpty, isNotEmpty) don't need value2!
|
|
637
|
+
|
|
638
|
+
#### Number Comparison
|
|
639
|
+
|
|
640
|
+
**Greater than**:
|
|
641
|
+
```javascript
|
|
642
|
+
{
|
|
643
|
+
"conditions": {
|
|
644
|
+
"number": [
|
|
645
|
+
{
|
|
646
|
+
"value1": "={{$json.age}}",
|
|
647
|
+
"operation": "larger",
|
|
648
|
+
"value2": 18
|
|
649
|
+
}
|
|
650
|
+
]
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
```
|
|
654
|
+
|
|
655
|
+
#### Boolean Comparison
|
|
656
|
+
|
|
657
|
+
**Is true**:
|
|
658
|
+
```javascript
|
|
659
|
+
{
|
|
660
|
+
"conditions": {
|
|
661
|
+
"boolean": [
|
|
662
|
+
{
|
|
663
|
+
"value1": "={{$json.isActive}}",
|
|
664
|
+
"operation": "true"
|
|
665
|
+
// Unary - no value2
|
|
666
|
+
}
|
|
667
|
+
]
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
```
|
|
671
|
+
|
|
672
|
+
#### Multiple Conditions (AND)
|
|
673
|
+
|
|
674
|
+
**All must match**:
|
|
675
|
+
```javascript
|
|
676
|
+
{
|
|
677
|
+
"conditions": {
|
|
678
|
+
"string": [
|
|
679
|
+
{
|
|
680
|
+
"value1": "={{$json.status}}",
|
|
681
|
+
"operation": "equals",
|
|
682
|
+
"value2": "active"
|
|
683
|
+
}
|
|
684
|
+
],
|
|
685
|
+
"number": [
|
|
686
|
+
{
|
|
687
|
+
"value1": "={{$json.age}}",
|
|
688
|
+
"operation": "larger",
|
|
689
|
+
"value2": 18
|
|
690
|
+
}
|
|
691
|
+
]
|
|
692
|
+
},
|
|
693
|
+
"combineOperation": "all" // AND logic
|
|
694
|
+
}
|
|
695
|
+
```
|
|
696
|
+
|
|
697
|
+
#### Multiple Conditions (OR)
|
|
698
|
+
|
|
699
|
+
**Any can match**:
|
|
700
|
+
```javascript
|
|
701
|
+
{
|
|
702
|
+
"conditions": {
|
|
703
|
+
"string": [
|
|
704
|
+
{
|
|
705
|
+
"value1": "={{$json.status}}",
|
|
706
|
+
"operation": "equals",
|
|
707
|
+
"value2": "active"
|
|
708
|
+
},
|
|
709
|
+
{
|
|
710
|
+
"value1": "={{$json.status}}",
|
|
711
|
+
"operation": "equals",
|
|
712
|
+
"value2": "pending"
|
|
713
|
+
}
|
|
714
|
+
]
|
|
715
|
+
},
|
|
716
|
+
"combineOperation": "any" // OR logic
|
|
717
|
+
}
|
|
718
|
+
```
|
|
719
|
+
|
|
720
|
+
---
|
|
721
|
+
|
|
722
|
+
### Switch (nodes-base.switch)
|
|
723
|
+
|
|
724
|
+
Multi-way routing - 18% of workflows
|
|
725
|
+
|
|
726
|
+
#### Basic Switch
|
|
727
|
+
|
|
728
|
+
**Minimal**:
|
|
729
|
+
```javascript
|
|
730
|
+
{
|
|
731
|
+
"mode": "rules",
|
|
732
|
+
"rules": {
|
|
733
|
+
"rules": [
|
|
734
|
+
{
|
|
735
|
+
"conditions": {
|
|
736
|
+
"string": [
|
|
737
|
+
{
|
|
738
|
+
"value1": "={{$json.status}}",
|
|
739
|
+
"operation": "equals",
|
|
740
|
+
"value2": "active"
|
|
741
|
+
}
|
|
742
|
+
]
|
|
743
|
+
}
|
|
744
|
+
},
|
|
745
|
+
{
|
|
746
|
+
"conditions": {
|
|
747
|
+
"string": [
|
|
748
|
+
{
|
|
749
|
+
"value1": "={{$json.status}}",
|
|
750
|
+
"operation": "equals",
|
|
751
|
+
"value2": "pending"
|
|
752
|
+
}
|
|
753
|
+
]
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
]
|
|
757
|
+
},
|
|
758
|
+
"fallbackOutput": "extra" // Catch-all for non-matching
|
|
759
|
+
}
|
|
760
|
+
```
|
|
761
|
+
|
|
762
|
+
**Gotcha**: Number of rules must match number of outputs!
|
|
763
|
+
|
|
764
|
+
---
|
|
765
|
+
|
|
766
|
+
## AI Nodes
|
|
767
|
+
|
|
768
|
+
### OpenAI (nodes-langchain.openAi)
|
|
769
|
+
|
|
770
|
+
AI operations - 234 templates
|
|
771
|
+
|
|
772
|
+
#### Chat Completion
|
|
773
|
+
|
|
774
|
+
**Minimal**:
|
|
775
|
+
```javascript
|
|
776
|
+
{
|
|
777
|
+
"resource": "chat",
|
|
778
|
+
"operation": "complete",
|
|
779
|
+
"messages": {
|
|
780
|
+
"values": [
|
|
781
|
+
{
|
|
782
|
+
"role": "user",
|
|
783
|
+
"content": "={{$json.prompt}}"
|
|
784
|
+
}
|
|
785
|
+
]
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
```
|
|
789
|
+
|
|
790
|
+
**With system prompt**:
|
|
791
|
+
```javascript
|
|
792
|
+
{
|
|
793
|
+
"resource": "chat",
|
|
794
|
+
"operation": "complete",
|
|
795
|
+
"messages": {
|
|
796
|
+
"values": [
|
|
797
|
+
{
|
|
798
|
+
"role": "system",
|
|
799
|
+
"content": "You are a helpful assistant specialized in customer support."
|
|
800
|
+
},
|
|
801
|
+
{
|
|
802
|
+
"role": "user",
|
|
803
|
+
"content": "={{$json.userMessage}}"
|
|
804
|
+
}
|
|
805
|
+
]
|
|
806
|
+
},
|
|
807
|
+
"options": {
|
|
808
|
+
"temperature": 0.7,
|
|
809
|
+
"maxTokens": 500
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
```
|
|
813
|
+
|
|
814
|
+
---
|
|
815
|
+
|
|
816
|
+
## Schedule Nodes
|
|
817
|
+
|
|
818
|
+
### Schedule Trigger (nodes-base.scheduleTrigger)
|
|
819
|
+
|
|
820
|
+
Time-based workflows - 28% have schedule triggers
|
|
821
|
+
|
|
822
|
+
#### Daily at Specific Time
|
|
823
|
+
|
|
824
|
+
**Minimal**:
|
|
825
|
+
```javascript
|
|
826
|
+
{
|
|
827
|
+
"rule": {
|
|
828
|
+
"interval": [
|
|
829
|
+
{
|
|
830
|
+
"field": "hours",
|
|
831
|
+
"hoursInterval": 24
|
|
832
|
+
}
|
|
833
|
+
],
|
|
834
|
+
"hour": 9,
|
|
835
|
+
"minute": 0,
|
|
836
|
+
"timezone": "America/New_York"
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
```
|
|
840
|
+
|
|
841
|
+
**Gotcha**: Always set timezone explicitly!
|
|
842
|
+
|
|
843
|
+
```javascript
|
|
844
|
+
// ❌ Bad - uses server timezone
|
|
845
|
+
{
|
|
846
|
+
"rule": {
|
|
847
|
+
"interval": [...]
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
// ✅ Good - explicit timezone
|
|
852
|
+
{
|
|
853
|
+
"rule": {
|
|
854
|
+
"interval": [...],
|
|
855
|
+
"timezone": "America/New_York"
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
```
|
|
859
|
+
|
|
860
|
+
#### Every N Minutes
|
|
861
|
+
|
|
862
|
+
**Minimal**:
|
|
863
|
+
```javascript
|
|
864
|
+
{
|
|
865
|
+
"rule": {
|
|
866
|
+
"interval": [
|
|
867
|
+
{
|
|
868
|
+
"field": "minutes",
|
|
869
|
+
"minutesInterval": 15
|
|
870
|
+
}
|
|
871
|
+
]
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
```
|
|
875
|
+
|
|
876
|
+
#### Cron Expression
|
|
877
|
+
|
|
878
|
+
**Advanced scheduling**:
|
|
879
|
+
```javascript
|
|
880
|
+
{
|
|
881
|
+
"mode": "cron",
|
|
882
|
+
"cronExpression": "0 */2 * * *", // Every 2 hours
|
|
883
|
+
"timezone": "America/New_York"
|
|
884
|
+
}
|
|
885
|
+
```
|
|
886
|
+
|
|
887
|
+
---
|
|
888
|
+
|
|
889
|
+
## Summary
|
|
890
|
+
|
|
891
|
+
**Key Patterns by Category**:
|
|
892
|
+
|
|
893
|
+
| Category | Most Common | Key Gotcha |
|
|
894
|
+
|---|---|---|
|
|
895
|
+
| HTTP/API | GET, POST JSON | Remember sendBody: true |
|
|
896
|
+
| Webhooks | POST receiver | Data under $json.body |
|
|
897
|
+
| Communication | Slack post | Channel format (#name) |
|
|
898
|
+
| Database | SELECT with params | Use parameterized queries |
|
|
899
|
+
| Transform | Set assignments | Correct type per field |
|
|
900
|
+
| Conditional | IF string equals | Unary vs binary operators |
|
|
901
|
+
| AI | OpenAI chat | System + user messages |
|
|
902
|
+
| Schedule | Daily at time | Set timezone explicitly |
|
|
903
|
+
|
|
904
|
+
**Configuration Approach**:
|
|
905
|
+
1. Use patterns as starting point
|
|
906
|
+
2. Adapt to your use case
|
|
907
|
+
3. Validate configuration
|
|
908
|
+
4. Iterate based on errors
|
|
909
|
+
5. Deploy when valid
|
|
910
|
+
|
|
911
|
+
**Related Files**:
|
|
912
|
+
- **[SKILL.md](SKILL.md)** - Configuration workflow and philosophy
|
|
913
|
+
- **[DEPENDENCIES.md](DEPENDENCIES.md)** - Property dependency rules
|