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,699 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: n8n-code-javascript
|
|
3
|
+
description: Write JavaScript code in n8n Code nodes. Use when writing JavaScript in n8n, using $input/$json/$node syntax, making HTTP requests with $helpers, working with dates using DateTime, troubleshooting Code node errors, or choosing between Code node modes.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# JavaScript Code Node
|
|
7
|
+
|
|
8
|
+
Expert guidance for writing JavaScript code in n8n Code nodes.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Quick Start
|
|
13
|
+
|
|
14
|
+
```javascript
|
|
15
|
+
// Basic template for Code nodes
|
|
16
|
+
const items = $input.all();
|
|
17
|
+
|
|
18
|
+
// Process data
|
|
19
|
+
const processed = items.map(item => ({
|
|
20
|
+
json: {
|
|
21
|
+
...item.json,
|
|
22
|
+
processed: true,
|
|
23
|
+
timestamp: new Date().toISOString()
|
|
24
|
+
}
|
|
25
|
+
}));
|
|
26
|
+
|
|
27
|
+
return processed;
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Essential Rules
|
|
31
|
+
|
|
32
|
+
1. **Choose "Run Once for All Items" mode** (recommended for most use cases)
|
|
33
|
+
2. **Access data**: `$input.all()`, `$input.first()`, or `$input.item`
|
|
34
|
+
3. **CRITICAL**: Must return `[{json: {...}}]` format
|
|
35
|
+
4. **CRITICAL**: Webhook data is under `$json.body` (not `$json` directly)
|
|
36
|
+
5. **Built-ins available**: $helpers.httpRequest(), DateTime (Luxon), $jmespath()
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Mode Selection Guide
|
|
41
|
+
|
|
42
|
+
The Code node offers two execution modes. Choose based on your use case:
|
|
43
|
+
|
|
44
|
+
### Run Once for All Items (Recommended - Default)
|
|
45
|
+
|
|
46
|
+
**Use this mode for:** 95% of use cases
|
|
47
|
+
|
|
48
|
+
- **How it works**: Code executes **once** regardless of input count
|
|
49
|
+
- **Data access**: `$input.all()` or `items` array
|
|
50
|
+
- **Best for**: Aggregation, filtering, batch processing, transformations, API calls with all data
|
|
51
|
+
- **Performance**: Faster for multiple items (single execution)
|
|
52
|
+
|
|
53
|
+
```javascript
|
|
54
|
+
// Example: Calculate total from all items
|
|
55
|
+
const allItems = $input.all();
|
|
56
|
+
const total = allItems.reduce((sum, item) => sum + (item.json.amount || 0), 0);
|
|
57
|
+
|
|
58
|
+
return [{
|
|
59
|
+
json: {
|
|
60
|
+
total,
|
|
61
|
+
count: allItems.length,
|
|
62
|
+
average: total / allItems.length
|
|
63
|
+
}
|
|
64
|
+
}];
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**When to use:**
|
|
68
|
+
- ✅ Comparing items across the dataset
|
|
69
|
+
- ✅ Calculating totals, averages, or statistics
|
|
70
|
+
- ✅ Sorting or ranking items
|
|
71
|
+
- ✅ Deduplication
|
|
72
|
+
- ✅ Building aggregated reports
|
|
73
|
+
- ✅ Combining data from multiple items
|
|
74
|
+
|
|
75
|
+
### Run Once for Each Item
|
|
76
|
+
|
|
77
|
+
**Use this mode for:** Specialized cases only
|
|
78
|
+
|
|
79
|
+
- **How it works**: Code executes **separately** for each input item
|
|
80
|
+
- **Data access**: `$input.item` or `$item`
|
|
81
|
+
- **Best for**: Item-specific logic, independent operations, per-item validation
|
|
82
|
+
- **Performance**: Slower for large datasets (multiple executions)
|
|
83
|
+
|
|
84
|
+
```javascript
|
|
85
|
+
// Example: Add processing timestamp to each item
|
|
86
|
+
const item = $input.item;
|
|
87
|
+
|
|
88
|
+
return [{
|
|
89
|
+
json: {
|
|
90
|
+
...item.json,
|
|
91
|
+
processed: true,
|
|
92
|
+
processedAt: new Date().toISOString()
|
|
93
|
+
}
|
|
94
|
+
}];
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**When to use:**
|
|
98
|
+
- ✅ Each item needs independent API call
|
|
99
|
+
- ✅ Per-item validation with different error handling
|
|
100
|
+
- ✅ Item-specific transformations based on item properties
|
|
101
|
+
- ✅ When items must be processed separately for business logic
|
|
102
|
+
|
|
103
|
+
**Decision Shortcut:**
|
|
104
|
+
- **Need to look at multiple items?** → Use "All Items" mode
|
|
105
|
+
- **Each item completely independent?** → Use "Each Item" mode
|
|
106
|
+
- **Not sure?** → Use "All Items" mode (you can always loop inside)
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## Data Access Patterns
|
|
111
|
+
|
|
112
|
+
### Pattern 1: $input.all() - Most Common
|
|
113
|
+
|
|
114
|
+
**Use when**: Processing arrays, batch operations, aggregations
|
|
115
|
+
|
|
116
|
+
```javascript
|
|
117
|
+
// Get all items from previous node
|
|
118
|
+
const allItems = $input.all();
|
|
119
|
+
|
|
120
|
+
// Filter, map, reduce as needed
|
|
121
|
+
const valid = allItems.filter(item => item.json.status === 'active');
|
|
122
|
+
const mapped = valid.map(item => ({
|
|
123
|
+
json: {
|
|
124
|
+
id: item.json.id,
|
|
125
|
+
name: item.json.name
|
|
126
|
+
}
|
|
127
|
+
}));
|
|
128
|
+
|
|
129
|
+
return mapped;
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Pattern 2: $input.first() - Very Common
|
|
133
|
+
|
|
134
|
+
**Use when**: Working with single objects, API responses, first-in-first-out
|
|
135
|
+
|
|
136
|
+
```javascript
|
|
137
|
+
// Get first item only
|
|
138
|
+
const firstItem = $input.first();
|
|
139
|
+
const data = firstItem.json;
|
|
140
|
+
|
|
141
|
+
return [{
|
|
142
|
+
json: {
|
|
143
|
+
result: processData(data),
|
|
144
|
+
processedAt: new Date().toISOString()
|
|
145
|
+
}
|
|
146
|
+
}];
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Pattern 3: $input.item - Each Item Mode Only
|
|
150
|
+
|
|
151
|
+
**Use when**: In "Run Once for Each Item" mode
|
|
152
|
+
|
|
153
|
+
```javascript
|
|
154
|
+
// Current item in loop (Each Item mode only)
|
|
155
|
+
const currentItem = $input.item;
|
|
156
|
+
|
|
157
|
+
return [{
|
|
158
|
+
json: {
|
|
159
|
+
...currentItem.json,
|
|
160
|
+
itemProcessed: true
|
|
161
|
+
}
|
|
162
|
+
}];
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Pattern 4: $node - Reference Other Nodes
|
|
166
|
+
|
|
167
|
+
**Use when**: Need data from specific nodes in workflow
|
|
168
|
+
|
|
169
|
+
```javascript
|
|
170
|
+
// Get output from specific node
|
|
171
|
+
const webhookData = $node["Webhook"].json;
|
|
172
|
+
const httpData = $node["HTTP Request"].json;
|
|
173
|
+
|
|
174
|
+
return [{
|
|
175
|
+
json: {
|
|
176
|
+
combined: {
|
|
177
|
+
webhook: webhookData,
|
|
178
|
+
api: httpData
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}];
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
**See**: [DATA_ACCESS.md](DATA_ACCESS.md) for comprehensive guide
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Critical: Webhook Data Structure
|
|
189
|
+
|
|
190
|
+
**MOST COMMON MISTAKE**: Webhook data is nested under `.body`
|
|
191
|
+
|
|
192
|
+
```javascript
|
|
193
|
+
// ❌ WRONG - Will return undefined
|
|
194
|
+
const name = $json.name;
|
|
195
|
+
const email = $json.email;
|
|
196
|
+
|
|
197
|
+
// ✅ CORRECT - Webhook data is under .body
|
|
198
|
+
const name = $json.body.name;
|
|
199
|
+
const email = $json.body.email;
|
|
200
|
+
|
|
201
|
+
// Or with $input
|
|
202
|
+
const webhookData = $input.first().json.body;
|
|
203
|
+
const name = webhookData.name;
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
**Why**: Webhook node wraps all request data under `body` property. This includes POST data, query parameters, and JSON payloads.
|
|
207
|
+
|
|
208
|
+
**See**: [DATA_ACCESS.md](DATA_ACCESS.md) for full webhook structure details
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## Return Format Requirements
|
|
213
|
+
|
|
214
|
+
**CRITICAL RULE**: Always return array of objects with `json` property
|
|
215
|
+
|
|
216
|
+
### Correct Return Formats
|
|
217
|
+
|
|
218
|
+
```javascript
|
|
219
|
+
// ✅ Single result
|
|
220
|
+
return [{
|
|
221
|
+
json: {
|
|
222
|
+
field1: value1,
|
|
223
|
+
field2: value2
|
|
224
|
+
}
|
|
225
|
+
}];
|
|
226
|
+
|
|
227
|
+
// ✅ Multiple results
|
|
228
|
+
return [
|
|
229
|
+
{json: {id: 1, data: 'first'}},
|
|
230
|
+
{json: {id: 2, data: 'second'}}
|
|
231
|
+
];
|
|
232
|
+
|
|
233
|
+
// ✅ Transformed array
|
|
234
|
+
const transformed = $input.all()
|
|
235
|
+
.filter(item => item.json.valid)
|
|
236
|
+
.map(item => ({
|
|
237
|
+
json: {
|
|
238
|
+
id: item.json.id,
|
|
239
|
+
processed: true
|
|
240
|
+
}
|
|
241
|
+
}));
|
|
242
|
+
return transformed;
|
|
243
|
+
|
|
244
|
+
// ✅ Empty result (when no data to return)
|
|
245
|
+
return [];
|
|
246
|
+
|
|
247
|
+
// ✅ Conditional return
|
|
248
|
+
if (shouldProcess) {
|
|
249
|
+
return [{json: processedData}];
|
|
250
|
+
} else {
|
|
251
|
+
return [];
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### Incorrect Return Formats
|
|
256
|
+
|
|
257
|
+
```javascript
|
|
258
|
+
// ❌ WRONG: Object without array wrapper
|
|
259
|
+
return {
|
|
260
|
+
json: {field: value}
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
// ❌ WRONG: Array without json wrapper
|
|
264
|
+
return [{field: value}];
|
|
265
|
+
|
|
266
|
+
// ❌ WRONG: Plain string
|
|
267
|
+
return "processed";
|
|
268
|
+
|
|
269
|
+
// ❌ WRONG: Raw data without mapping
|
|
270
|
+
return $input.all(); // Missing .map()
|
|
271
|
+
|
|
272
|
+
// ❌ WRONG: Incomplete structure
|
|
273
|
+
return [{data: value}]; // Should be {json: value}
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
**Why it matters**: Next nodes expect array format. Incorrect format causes workflow execution to fail.
|
|
277
|
+
|
|
278
|
+
**See**: [ERROR_PATTERNS.md](ERROR_PATTERNS.md) #3 for detailed error solutions
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
## Common Patterns Overview
|
|
283
|
+
|
|
284
|
+
Based on production workflows, here are the most useful patterns:
|
|
285
|
+
|
|
286
|
+
### 1. Multi-Source Data Aggregation
|
|
287
|
+
Combine data from multiple APIs, webhooks, or nodes
|
|
288
|
+
|
|
289
|
+
```javascript
|
|
290
|
+
const allItems = $input.all();
|
|
291
|
+
const results = [];
|
|
292
|
+
|
|
293
|
+
for (const item of allItems) {
|
|
294
|
+
const sourceName = item.json.name || 'Unknown';
|
|
295
|
+
// Parse source-specific structure
|
|
296
|
+
if (sourceName === 'API1' && item.json.data) {
|
|
297
|
+
results.push({
|
|
298
|
+
json: {
|
|
299
|
+
title: item.json.data.title,
|
|
300
|
+
source: 'API1'
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
return results;
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### 2. Filtering with Regex
|
|
310
|
+
Extract patterns, mentions, or keywords from text
|
|
311
|
+
|
|
312
|
+
```javascript
|
|
313
|
+
const pattern = /\b([A-Z]{2,5})\b/g;
|
|
314
|
+
const matches = {};
|
|
315
|
+
|
|
316
|
+
for (const item of $input.all()) {
|
|
317
|
+
const text = item.json.text;
|
|
318
|
+
const found = text.match(pattern);
|
|
319
|
+
|
|
320
|
+
if (found) {
|
|
321
|
+
found.forEach(match => {
|
|
322
|
+
matches[match] = (matches[match] || 0) + 1;
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
return [{json: {matches}}];
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
### 3. Data Transformation & Enrichment
|
|
331
|
+
Map fields, normalize formats, add computed fields
|
|
332
|
+
|
|
333
|
+
```javascript
|
|
334
|
+
const items = $input.all();
|
|
335
|
+
|
|
336
|
+
return items.map(item => {
|
|
337
|
+
const data = item.json;
|
|
338
|
+
const nameParts = data.name.split(' ');
|
|
339
|
+
|
|
340
|
+
return {
|
|
341
|
+
json: {
|
|
342
|
+
first_name: nameParts[0],
|
|
343
|
+
last_name: nameParts.slice(1).join(' '),
|
|
344
|
+
email: data.email,
|
|
345
|
+
created_at: new Date().toISOString()
|
|
346
|
+
}
|
|
347
|
+
};
|
|
348
|
+
});
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
### 4. Top N Filtering & Ranking
|
|
352
|
+
Sort and limit results
|
|
353
|
+
|
|
354
|
+
```javascript
|
|
355
|
+
const items = $input.all();
|
|
356
|
+
|
|
357
|
+
const topItems = items
|
|
358
|
+
.sort((a, b) => (b.json.score || 0) - (a.json.score || 0))
|
|
359
|
+
.slice(0, 10);
|
|
360
|
+
|
|
361
|
+
return topItems.map(item => ({json: item.json}));
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
### 5. Aggregation & Reporting
|
|
365
|
+
Sum, count, group data
|
|
366
|
+
|
|
367
|
+
```javascript
|
|
368
|
+
const items = $input.all();
|
|
369
|
+
const total = items.reduce((sum, item) => sum + (item.json.amount || 0), 0);
|
|
370
|
+
|
|
371
|
+
return [{
|
|
372
|
+
json: {
|
|
373
|
+
total,
|
|
374
|
+
count: items.length,
|
|
375
|
+
average: total / items.length,
|
|
376
|
+
timestamp: new Date().toISOString()
|
|
377
|
+
}
|
|
378
|
+
}];
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
**See**: [COMMON_PATTERNS.md](COMMON_PATTERNS.md) for 10 detailed production patterns
|
|
382
|
+
|
|
383
|
+
---
|
|
384
|
+
|
|
385
|
+
## Error Prevention - Top 5 Mistakes
|
|
386
|
+
|
|
387
|
+
### #1: Empty Code or Missing Return (Most Common)
|
|
388
|
+
|
|
389
|
+
```javascript
|
|
390
|
+
// ❌ WRONG: No return statement
|
|
391
|
+
const items = $input.all();
|
|
392
|
+
// ... processing code ...
|
|
393
|
+
// Forgot to return!
|
|
394
|
+
|
|
395
|
+
// ✅ CORRECT: Always return data
|
|
396
|
+
const items = $input.all();
|
|
397
|
+
// ... processing ...
|
|
398
|
+
return items.map(item => ({json: item.json}));
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
### #2: Expression Syntax Confusion
|
|
402
|
+
|
|
403
|
+
```javascript
|
|
404
|
+
// ❌ WRONG: Using n8n expression syntax in code
|
|
405
|
+
const value = "{{ $json.field }}";
|
|
406
|
+
|
|
407
|
+
// ✅ CORRECT: Use JavaScript template literals
|
|
408
|
+
const value = `${$json.field}`;
|
|
409
|
+
|
|
410
|
+
// ✅ CORRECT: Direct access
|
|
411
|
+
const value = $input.first().json.field;
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
### #3: Incorrect Return Wrapper
|
|
415
|
+
|
|
416
|
+
```javascript
|
|
417
|
+
// ❌ WRONG: Returning object instead of array
|
|
418
|
+
return {json: {result: 'success'}};
|
|
419
|
+
|
|
420
|
+
// ✅ CORRECT: Array wrapper required
|
|
421
|
+
return [{json: {result: 'success'}}];
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
### #4: Missing Null Checks
|
|
425
|
+
|
|
426
|
+
```javascript
|
|
427
|
+
// ❌ WRONG: Crashes if field doesn't exist
|
|
428
|
+
const value = item.json.user.email;
|
|
429
|
+
|
|
430
|
+
// ✅ CORRECT: Safe access with optional chaining
|
|
431
|
+
const value = item.json?.user?.email || 'no-email@example.com';
|
|
432
|
+
|
|
433
|
+
// ✅ CORRECT: Guard clause
|
|
434
|
+
if (!item.json.user) {
|
|
435
|
+
return [];
|
|
436
|
+
}
|
|
437
|
+
const value = item.json.user.email;
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
### #5: Webhook Body Nesting
|
|
441
|
+
|
|
442
|
+
```javascript
|
|
443
|
+
// ❌ WRONG: Direct access to webhook data
|
|
444
|
+
const email = $json.email;
|
|
445
|
+
|
|
446
|
+
// ✅ CORRECT: Webhook data under .body
|
|
447
|
+
const email = $json.body.email;
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
**See**: [ERROR_PATTERNS.md](ERROR_PATTERNS.md) for comprehensive error guide
|
|
451
|
+
|
|
452
|
+
---
|
|
453
|
+
|
|
454
|
+
## Built-in Functions & Helpers
|
|
455
|
+
|
|
456
|
+
### $helpers.httpRequest()
|
|
457
|
+
|
|
458
|
+
Make HTTP requests from within code:
|
|
459
|
+
|
|
460
|
+
```javascript
|
|
461
|
+
const response = await $helpers.httpRequest({
|
|
462
|
+
method: 'GET',
|
|
463
|
+
url: 'https://api.example.com/data',
|
|
464
|
+
headers: {
|
|
465
|
+
'Authorization': 'Bearer token',
|
|
466
|
+
'Content-Type': 'application/json'
|
|
467
|
+
}
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
return [{json: {data: response}}];
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
### DateTime (Luxon)
|
|
474
|
+
|
|
475
|
+
Date and time operations:
|
|
476
|
+
|
|
477
|
+
```javascript
|
|
478
|
+
// Current time
|
|
479
|
+
const now = DateTime.now();
|
|
480
|
+
|
|
481
|
+
// Format dates
|
|
482
|
+
const formatted = now.toFormat('yyyy-MM-dd');
|
|
483
|
+
const iso = now.toISO();
|
|
484
|
+
|
|
485
|
+
// Date arithmetic
|
|
486
|
+
const tomorrow = now.plus({days: 1});
|
|
487
|
+
const lastWeek = now.minus({weeks: 1});
|
|
488
|
+
|
|
489
|
+
return [{
|
|
490
|
+
json: {
|
|
491
|
+
today: formatted,
|
|
492
|
+
tomorrow: tomorrow.toFormat('yyyy-MM-dd')
|
|
493
|
+
}
|
|
494
|
+
}];
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
### $jmespath()
|
|
498
|
+
|
|
499
|
+
Query JSON structures:
|
|
500
|
+
|
|
501
|
+
```javascript
|
|
502
|
+
const data = $input.first().json;
|
|
503
|
+
|
|
504
|
+
// Filter array
|
|
505
|
+
const adults = $jmespath(data, 'users[?age >= `18`]');
|
|
506
|
+
|
|
507
|
+
// Extract fields
|
|
508
|
+
const names = $jmespath(data, 'users[*].name');
|
|
509
|
+
|
|
510
|
+
return [{json: {adults, names}}];
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
**See**: [BUILTIN_FUNCTIONS.md](BUILTIN_FUNCTIONS.md) for complete reference
|
|
514
|
+
|
|
515
|
+
---
|
|
516
|
+
|
|
517
|
+
## Best Practices
|
|
518
|
+
|
|
519
|
+
### 1. Always Validate Input Data
|
|
520
|
+
|
|
521
|
+
```javascript
|
|
522
|
+
const items = $input.all();
|
|
523
|
+
|
|
524
|
+
// Check if data exists
|
|
525
|
+
if (!items || items.length === 0) {
|
|
526
|
+
return [];
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
// Validate structure
|
|
530
|
+
if (!items[0].json) {
|
|
531
|
+
return [{json: {error: 'Invalid input format'}}];
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
// Continue processing...
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
### 2. Use Try-Catch for Error Handling
|
|
538
|
+
|
|
539
|
+
```javascript
|
|
540
|
+
try {
|
|
541
|
+
const response = await $helpers.httpRequest({
|
|
542
|
+
url: 'https://api.example.com/data'
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
return [{json: {success: true, data: response}}];
|
|
546
|
+
} catch (error) {
|
|
547
|
+
return [{
|
|
548
|
+
json: {
|
|
549
|
+
success: false,
|
|
550
|
+
error: error.message
|
|
551
|
+
}
|
|
552
|
+
}];
|
|
553
|
+
}
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
### 3. Prefer Array Methods Over Loops
|
|
557
|
+
|
|
558
|
+
```javascript
|
|
559
|
+
// ✅ GOOD: Functional approach
|
|
560
|
+
const processed = $input.all()
|
|
561
|
+
.filter(item => item.json.valid)
|
|
562
|
+
.map(item => ({json: {id: item.json.id}}));
|
|
563
|
+
|
|
564
|
+
// ❌ SLOWER: Manual loop
|
|
565
|
+
const processed = [];
|
|
566
|
+
for (const item of $input.all()) {
|
|
567
|
+
if (item.json.valid) {
|
|
568
|
+
processed.push({json: {id: item.json.id}});
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
### 4. Filter Early, Process Late
|
|
574
|
+
|
|
575
|
+
```javascript
|
|
576
|
+
// ✅ GOOD: Filter first to reduce processing
|
|
577
|
+
const processed = $input.all()
|
|
578
|
+
.filter(item => item.json.status === 'active') // Reduce dataset first
|
|
579
|
+
.map(item => expensiveTransformation(item)); // Then transform
|
|
580
|
+
|
|
581
|
+
// ❌ WASTEFUL: Transform everything, then filter
|
|
582
|
+
const processed = $input.all()
|
|
583
|
+
.map(item => expensiveTransformation(item)) // Wastes CPU
|
|
584
|
+
.filter(item => item.json.status === 'active');
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
### 5. Use Descriptive Variable Names
|
|
588
|
+
|
|
589
|
+
```javascript
|
|
590
|
+
// ✅ GOOD: Clear intent
|
|
591
|
+
const activeUsers = $input.all().filter(item => item.json.active);
|
|
592
|
+
const totalRevenue = activeUsers.reduce((sum, user) => sum + user.json.revenue, 0);
|
|
593
|
+
|
|
594
|
+
// ❌ BAD: Unclear purpose
|
|
595
|
+
const a = $input.all().filter(item => item.json.active);
|
|
596
|
+
const t = a.reduce((s, u) => s + u.json.revenue, 0);
|
|
597
|
+
```
|
|
598
|
+
|
|
599
|
+
### 6. Debug with console.log()
|
|
600
|
+
|
|
601
|
+
```javascript
|
|
602
|
+
// Debug statements appear in browser console
|
|
603
|
+
const items = $input.all();
|
|
604
|
+
console.log(`Processing ${items.length} items`);
|
|
605
|
+
|
|
606
|
+
for (const item of items) {
|
|
607
|
+
console.log('Item data:', item.json);
|
|
608
|
+
// Process...
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
return result;
|
|
612
|
+
```
|
|
613
|
+
|
|
614
|
+
---
|
|
615
|
+
|
|
616
|
+
## When to Use Code Node
|
|
617
|
+
|
|
618
|
+
Use Code node when:
|
|
619
|
+
- ✅ Complex transformations requiring multiple steps
|
|
620
|
+
- ✅ Custom calculations or business logic
|
|
621
|
+
- ✅ Recursive operations
|
|
622
|
+
- ✅ API response parsing with complex structure
|
|
623
|
+
- ✅ Multi-step conditionals
|
|
624
|
+
- ✅ Data aggregation across items
|
|
625
|
+
|
|
626
|
+
Consider other nodes when:
|
|
627
|
+
- ❌ Simple field mapping → Use **Set** node
|
|
628
|
+
- ❌ Basic filtering → Use **Filter** node
|
|
629
|
+
- ❌ Simple conditionals → Use **IF** or **Switch** node
|
|
630
|
+
- ❌ HTTP requests only → Use **HTTP Request** node
|
|
631
|
+
|
|
632
|
+
**Code node excels at**: Complex logic that would require chaining many simple nodes
|
|
633
|
+
|
|
634
|
+
---
|
|
635
|
+
|
|
636
|
+
## Integration with Other Skills
|
|
637
|
+
|
|
638
|
+
### Works With:
|
|
639
|
+
|
|
640
|
+
**n8n Expression Syntax**:
|
|
641
|
+
- Expressions use `{{ }}` syntax in other nodes
|
|
642
|
+
- Code nodes use JavaScript directly (no `{{ }}`)
|
|
643
|
+
- When to use expressions vs code
|
|
644
|
+
|
|
645
|
+
**n8n MCP Tools Expert**:
|
|
646
|
+
- How to find Code node: `search_nodes({query: "code"})`
|
|
647
|
+
- Get configuration help: `get_node_essentials("nodes-base.code")`
|
|
648
|
+
- Validate code: `validate_node_operation()`
|
|
649
|
+
|
|
650
|
+
**n8n Node Configuration**:
|
|
651
|
+
- Mode selection (All Items vs Each Item)
|
|
652
|
+
- Language selection (JavaScript vs Python)
|
|
653
|
+
- Understanding property dependencies
|
|
654
|
+
|
|
655
|
+
**n8n Workflow Patterns**:
|
|
656
|
+
- Code nodes in transformation step
|
|
657
|
+
- Webhook → Code → API pattern
|
|
658
|
+
- Error handling in workflows
|
|
659
|
+
|
|
660
|
+
**n8n Validation Expert**:
|
|
661
|
+
- Validate Code node configuration
|
|
662
|
+
- Handle validation errors
|
|
663
|
+
- Auto-fix common issues
|
|
664
|
+
|
|
665
|
+
---
|
|
666
|
+
|
|
667
|
+
## Quick Reference Checklist
|
|
668
|
+
|
|
669
|
+
Before deploying Code nodes, verify:
|
|
670
|
+
|
|
671
|
+
- [ ] **Code is not empty** - Must have meaningful logic
|
|
672
|
+
- [ ] **Return statement exists** - Must return array of objects
|
|
673
|
+
- [ ] **Proper return format** - Each item: `{json: {...}}`
|
|
674
|
+
- [ ] **Data access correct** - Using `$input.all()`, `$input.first()`, or `$input.item`
|
|
675
|
+
- [ ] **No n8n expressions** - Use JavaScript template literals: `` `${value}` ``
|
|
676
|
+
- [ ] **Error handling** - Guard clauses for null/undefined inputs
|
|
677
|
+
- [ ] **Webhook data** - Access via `.body` if from webhook
|
|
678
|
+
- [ ] **Mode selection** - "All Items" for most cases
|
|
679
|
+
- [ ] **Performance** - Prefer map/filter over manual loops
|
|
680
|
+
- [ ] **Output consistent** - All code paths return same structure
|
|
681
|
+
|
|
682
|
+
---
|
|
683
|
+
|
|
684
|
+
## Additional Resources
|
|
685
|
+
|
|
686
|
+
### Related Files
|
|
687
|
+
- [DATA_ACCESS.md](DATA_ACCESS.md) - Comprehensive data access patterns
|
|
688
|
+
- [COMMON_PATTERNS.md](COMMON_PATTERNS.md) - 10 production-tested patterns
|
|
689
|
+
- [ERROR_PATTERNS.md](ERROR_PATTERNS.md) - Top 5 errors and solutions
|
|
690
|
+
- [BUILTIN_FUNCTIONS.md](BUILTIN_FUNCTIONS.md) - Complete built-in reference
|
|
691
|
+
|
|
692
|
+
### n8n Documentation
|
|
693
|
+
- Code Node Guide: https://docs.n8n.io/code/code-node/
|
|
694
|
+
- Built-in Methods: https://docs.n8n.io/code-examples/methods-variables-reference/
|
|
695
|
+
- Luxon Documentation: https://moment.github.io/luxon/
|
|
696
|
+
|
|
697
|
+
---
|
|
698
|
+
|
|
699
|
+
**Ready to write JavaScript in n8n Code nodes!** Start with simple transformations, use the error patterns guide to avoid common mistakes, and reference the pattern library for production-ready examples.
|