@awesomate/hosting-mcp 0.12.0 → 0.13.0

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.
Files changed (58) hide show
  1. package/dist/index.js +204 -8
  2. package/package.json +2 -2
  3. package/skill/awesomate-app-builder/SKILL.md +5 -1
  4. package/skill/awesomate-credentials/SKILL.md +1 -1
  5. package/skill/awesomate-hosting/SKILL.md +50 -159
  6. package/skill/awesomate-hosting/references/connect-troubleshooting.md +77 -0
  7. package/skill/awesomate-hosting/references/multi-account.md +33 -0
  8. package/skill/awesomate-hosting/references/rest-fallback.md +30 -0
  9. package/skill/awesomate-hosting/scripts/bootstrap.mjs +27 -7
  10. package/skill/awesomate-n8n/SKILL.md +153 -147
  11. package/skill/awesomate-n8n/evals/ai-agent-build/graders/grader.md +31 -0
  12. package/skill/awesomate-n8n/evals/ai-agent-build/prompt.md +1 -0
  13. package/skill/awesomate-n8n/evals/build-form-email/graders/grader.md +30 -0
  14. package/skill/awesomate-n8n/evals/build-form-email/prompt.md +1 -0
  15. package/skill/awesomate-n8n/evals/datatable-dedupe/graders/grader.md +32 -0
  16. package/skill/awesomate-n8n/evals/datatable-dedupe/prompt.md +2 -0
  17. package/skill/awesomate-n8n/evals/diagnose-failure/graders/grader.md +27 -0
  18. package/skill/awesomate-n8n/evals/diagnose-failure/prompt.md +2 -0
  19. package/skill/awesomate-n8n/evals/essentials-upsell/graders/grader.md +27 -0
  20. package/skill/awesomate-n8n/evals/essentials-upsell/prompt.md +2 -0
  21. package/skill/awesomate-n8n/evals/live-change-promote/graders/grader.md +35 -0
  22. package/skill/awesomate-n8n/evals/live-change-promote/prompt.md +2 -0
  23. package/skill/awesomate-n8n/evals/possibilities-grounded/graders/grader.md +28 -0
  24. package/skill/awesomate-n8n/evals/possibilities-grounded/prompt.md +1 -0
  25. package/skill/awesomate-n8n/evals/validated-not-done/graders/grader.md +27 -0
  26. package/skill/awesomate-n8n/evals/validated-not-done/prompt.md +2 -0
  27. package/skill/awesomate-n8n/evals/vars-not-env/graders/grader.md +26 -0
  28. package/skill/awesomate-n8n/evals/vars-not-env/prompt.md +2 -0
  29. package/skill/awesomate-n8n/evals/webhook-body-fix/graders/grader.md +26 -0
  30. package/skill/awesomate-n8n/evals/webhook-body-fix/prompt.md +3 -0
  31. package/skill/awesomate-n8n/references/ai-agents.md +135 -0
  32. package/skill/awesomate-n8n/references/datatables.md +105 -0
  33. package/skill/awesomate-n8n/references/{node-recipes.md → platform-notes.md} +56 -7
  34. package/skill/awesomate-n8n/references/possibilities.md +83 -0
  35. package/skill/awesomate-n8n/references/testing-policy.md +115 -0
  36. package/skill/awesomate-n8n/references/troubleshooting.md +69 -0
  37. package/skill/awesomate-n8n/references/upgrade-loop.md +98 -0
  38. package/skill/awesomate-n8n/references/vendor/MANIFEST.json +26 -0
  39. package/skill/awesomate-n8n/references/vendor/code-node/BUILTIN_FUNCTIONS.md +779 -0
  40. package/skill/awesomate-n8n/references/vendor/code-node/COMMON_PATTERNS.md +1123 -0
  41. package/skill/awesomate-n8n/references/vendor/code-node/DATA_ACCESS.md +797 -0
  42. package/skill/awesomate-n8n/references/vendor/code-node/ERROR_PATTERNS.md +776 -0
  43. package/skill/awesomate-n8n/references/vendor/code-node/SKILL.md +703 -0
  44. package/skill/awesomate-n8n/references/vendor/expressions/COMMON_MISTAKES.md +406 -0
  45. package/skill/awesomate-n8n/references/vendor/expressions/EXAMPLES.md +496 -0
  46. package/skill/awesomate-n8n/references/vendor/expressions/SKILL.md +525 -0
  47. package/skill/awesomate-n8n/references/vendor/node-configuration/DEPENDENCIES.md +743 -0
  48. package/skill/awesomate-n8n/references/vendor/node-configuration/OPERATION_PATTERNS.md +926 -0
  49. package/skill/awesomate-n8n/references/vendor/node-configuration/SKILL.md +583 -0
  50. package/skill/awesomate-n8n/references/vendor/validation/ERROR_CATALOG.md +781 -0
  51. package/skill/awesomate-n8n/references/vendor/validation/FALSE_POSITIVES.md +695 -0
  52. package/skill/awesomate-n8n/references/vendor/validation/SKILL.md +414 -0
  53. package/skill/awesomate-n8n/references/vendor/workflow-patterns/SKILL.md +413 -0
  54. package/skill/awesomate-n8n/references/vendor/workflow-patterns/ai_agent_workflow.md +797 -0
  55. package/skill/awesomate-n8n/references/vendor/workflow-patterns/database_operations.md +798 -0
  56. package/skill/awesomate-n8n/references/vendor/workflow-patterns/http_api_integration.md +747 -0
  57. package/skill/awesomate-n8n/references/vendor/workflow-patterns/scheduled_tasks.md +786 -0
  58. package/skill/awesomate-n8n/references/vendor/workflow-patterns/webhook_processing.md +558 -0
@@ -0,0 +1,797 @@
1
+ <!--
2
+ VENDORED from n8n-builder@d293559 (n8n-code-javascript/DATA_ACCESS.md) — DO NOT EDIT HERE.
3
+ Edit the source in ~/Projects/n8n-builder, then re-run:
4
+ node mcp/scripts/sync-n8n-references.mjs --write
5
+
6
+ Awesomate platform overrides — where this file conflicts with
7
+ ../platform-notes.md, platform-notes wins:
8
+ - $env is BLOCKED fleet-wide → use {{ $vars.key || 'fallback' }}
9
+ - Task runners are ON → no $helpers in Code nodes; use HTTP Request nodes
10
+ - Webhook payloads live at $json.body
11
+ - saveExecutionProgress must stay false
12
+ -->
13
+
14
+ # Data Access Patterns - JavaScript Code Node
15
+
16
+ Comprehensive guide to accessing data in n8n Code nodes using JavaScript.
17
+
18
+ ---
19
+
20
+ ## Overview
21
+
22
+ In n8n Code nodes, you access data from previous nodes using built-in variables and methods. Understanding which method to use is critical for correct workflow execution.
23
+
24
+ **Data Access Priority** (by common usage):
25
+ 1. **`$input.all()`** - Most common - Batch operations, aggregations
26
+ 2. **`$input.first()`** - Very common - Single item operations
27
+ 3. **`$input.item`** - Common - Each Item mode only
28
+ 4. **`$node["NodeName"].json`** - Specific node references
29
+ 5. **`$json`** - Direct current item (legacy, use `$input` instead)
30
+
31
+ ---
32
+
33
+ ## Pattern 1: $input.all() - Process All Items
34
+
35
+ **Usage**: Most common pattern for batch processing
36
+
37
+ **When to use:**
38
+ - Processing multiple records
39
+ - Aggregating data (sum, count, average)
40
+ - Filtering arrays
41
+ - Transforming datasets
42
+ - Comparing items
43
+ - Sorting or ranking
44
+
45
+ ### Basic Usage
46
+
47
+ ```javascript
48
+ // Get all items from previous node
49
+ const allItems = $input.all();
50
+
51
+ // allItems is an array of objects like:
52
+ // [
53
+ // {json: {id: 1, name: "Alice"}},
54
+ // {json: {id: 2, name: "Bob"}}
55
+ // ]
56
+
57
+ console.log(`Received ${allItems.length} items`);
58
+
59
+ return allItems;
60
+ ```
61
+
62
+ ### Example 1: Filter Active Items
63
+
64
+ ```javascript
65
+ const allItems = $input.all();
66
+
67
+ // Filter only active items
68
+ const activeItems = allItems.filter(item => item.json.status === 'active');
69
+
70
+ return activeItems;
71
+ ```
72
+
73
+ ### Example 2: Transform All Items
74
+
75
+ ```javascript
76
+ const allItems = $input.all();
77
+
78
+ // Map to new structure
79
+ const transformed = allItems.map(item => ({
80
+ json: {
81
+ id: item.json.id,
82
+ fullName: `${item.json.firstName} ${item.json.lastName}`,
83
+ email: item.json.email,
84
+ processedAt: new Date().toISOString()
85
+ }
86
+ }));
87
+
88
+ return transformed;
89
+ ```
90
+
91
+ ### Example 3: Aggregate Data
92
+
93
+ ```javascript
94
+ const allItems = $input.all();
95
+
96
+ // Calculate total
97
+ const total = allItems.reduce((sum, item) => {
98
+ return sum + (item.json.amount || 0);
99
+ }, 0);
100
+
101
+ return [{
102
+ json: {
103
+ total,
104
+ count: allItems.length,
105
+ average: total / allItems.length
106
+ }
107
+ }];
108
+ ```
109
+
110
+ ### Example 4: Sort and Limit
111
+
112
+ ```javascript
113
+ const allItems = $input.all();
114
+
115
+ // Get top 5 by score
116
+ const topFive = allItems
117
+ .sort((a, b) => (b.json.score || 0) - (a.json.score || 0))
118
+ .slice(0, 5);
119
+
120
+ return topFive.map(item => ({json: item.json}));
121
+ ```
122
+
123
+ ### Example 5: Group By Category
124
+
125
+ ```javascript
126
+ const allItems = $input.all();
127
+
128
+ // Group items by category
129
+ const grouped = {};
130
+
131
+ for (const item of allItems) {
132
+ const category = item.json.category || 'Uncategorized';
133
+
134
+ if (!grouped[category]) {
135
+ grouped[category] = [];
136
+ }
137
+
138
+ grouped[category].push(item.json);
139
+ }
140
+
141
+ // Convert to array format
142
+ return Object.entries(grouped).map(([category, items]) => ({
143
+ json: {
144
+ category,
145
+ items,
146
+ count: items.length
147
+ }
148
+ }));
149
+ ```
150
+
151
+ ### Example 6: Deduplicate by ID
152
+
153
+ ```javascript
154
+ const allItems = $input.all();
155
+
156
+ // Remove duplicates by ID
157
+ const seen = new Set();
158
+ const unique = [];
159
+
160
+ for (const item of allItems) {
161
+ const id = item.json.id;
162
+
163
+ if (!seen.has(id)) {
164
+ seen.add(id);
165
+ unique.push(item);
166
+ }
167
+ }
168
+
169
+ return unique;
170
+ ```
171
+
172
+ ---
173
+
174
+ ## Pattern 2: $input.first() - Get First Item
175
+
176
+ **Usage**: Very common for single-item operations
177
+
178
+ **When to use:**
179
+ - Previous node returns single object
180
+ - Working with API responses
181
+ - Getting initial/first data point
182
+ - Configuration or metadata access
183
+
184
+ ### Basic Usage
185
+
186
+ ```javascript
187
+ // Get first item from previous node
188
+ const firstItem = $input.first();
189
+
190
+ // Access the JSON data
191
+ const data = firstItem.json;
192
+
193
+ console.log('First item:', data);
194
+
195
+ return [{json: data}];
196
+ ```
197
+
198
+ ### Example 1: Process Single API Response
199
+
200
+ ```javascript
201
+ // Get API response (typically single object)
202
+ const response = $input.first().json;
203
+
204
+ // Extract what you need
205
+ return [{
206
+ json: {
207
+ userId: response.data.user.id,
208
+ userName: response.data.user.name,
209
+ status: response.status,
210
+ fetchedAt: new Date().toISOString()
211
+ }
212
+ }];
213
+ ```
214
+
215
+ ### Example 2: Transform Single Object
216
+
217
+ ```javascript
218
+ const data = $input.first().json;
219
+
220
+ // Transform structure
221
+ return [{
222
+ json: {
223
+ id: data.id,
224
+ contact: {
225
+ email: data.email,
226
+ phone: data.phone
227
+ },
228
+ address: {
229
+ street: data.street,
230
+ city: data.city,
231
+ zip: data.zip
232
+ }
233
+ }
234
+ }];
235
+ ```
236
+
237
+ ### Example 3: Validate Single Item
238
+
239
+ ```javascript
240
+ const item = $input.first().json;
241
+
242
+ // Validation logic
243
+ const isValid = item.email && item.email.includes('@');
244
+
245
+ return [{
246
+ json: {
247
+ ...item,
248
+ valid: isValid,
249
+ validatedAt: new Date().toISOString()
250
+ }
251
+ }];
252
+ ```
253
+
254
+ ### Example 4: Extract Nested Data
255
+
256
+ ```javascript
257
+ const response = $input.first().json;
258
+
259
+ // Navigate nested structure
260
+ const users = response.data?.users || [];
261
+
262
+ return users.map(user => ({
263
+ json: {
264
+ id: user.id,
265
+ name: user.profile?.name || 'Unknown',
266
+ email: user.contact?.email || 'no-email'
267
+ }
268
+ }));
269
+ ```
270
+
271
+ ### Example 5: Combine with Other Methods
272
+
273
+ ```javascript
274
+ // Get first item's data
275
+ const firstData = $input.first().json;
276
+
277
+ // Use it to filter all items
278
+ const allItems = $input.all();
279
+ const matching = allItems.filter(item =>
280
+ item.json.category === firstData.targetCategory
281
+ );
282
+
283
+ return matching;
284
+ ```
285
+
286
+ ---
287
+
288
+ ## Pattern 3: $input.item - Current Item (Each Item Mode)
289
+
290
+ **Usage**: Common in "Run Once for Each Item" mode
291
+
292
+ **When to use:**
293
+ - Mode is set to "Run Once for Each Item"
294
+ - Need to process items independently
295
+ - Per-item API calls or validations
296
+ - Item-specific error handling
297
+
298
+ **IMPORTANT**: Only use in "Each Item" mode. Will be undefined in "All Items" mode.
299
+
300
+ ### Basic Usage
301
+
302
+ ```javascript
303
+ // In "Run Once for Each Item" mode
304
+ const currentItem = $input.item;
305
+ const data = currentItem.json;
306
+
307
+ console.log('Processing item:', data.id);
308
+
309
+ return [{
310
+ json: {
311
+ ...data,
312
+ processed: true
313
+ }
314
+ }];
315
+ ```
316
+
317
+ ### Example 1: Add Processing Metadata
318
+
319
+ ```javascript
320
+ const item = $input.item;
321
+
322
+ return [{
323
+ json: {
324
+ ...item.json,
325
+ processed: true,
326
+ processedAt: new Date().toISOString(),
327
+ processingDuration: Math.random() * 1000 // Simulated duration
328
+ }
329
+ }];
330
+ ```
331
+
332
+ ### Example 2: Per-Item Validation
333
+
334
+ ```javascript
335
+ const item = $input.item;
336
+ const data = item.json;
337
+
338
+ // Validate this specific item
339
+ const errors = [];
340
+
341
+ if (!data.email) errors.push('Email required');
342
+ if (!data.name) errors.push('Name required');
343
+ if (data.age && data.age < 18) errors.push('Must be 18+');
344
+
345
+ return [{
346
+ json: {
347
+ ...data,
348
+ valid: errors.length === 0,
349
+ errors: errors.length > 0 ? errors : undefined
350
+ }
351
+ }];
352
+ ```
353
+
354
+ ### Example 3: Item-Specific API Call
355
+
356
+ > ⚠️ Legacy in-process instances only: `$helpers` is not defined under default n8n 2.x task runners — on those, use an HTTP Request node after this Code node instead.
357
+
358
+ ```javascript
359
+ const item = $input.item;
360
+ const userId = item.json.userId;
361
+
362
+ // Make API call specific to this item
363
+ const response = await $helpers.httpRequest({
364
+ method: 'GET',
365
+ url: `https://api.example.com/users/${userId}/details`
366
+ });
367
+
368
+ return [{
369
+ json: {
370
+ ...item.json,
371
+ details: response
372
+ }
373
+ }];
374
+ ```
375
+
376
+ ### Example 4: Conditional Processing
377
+
378
+ ```javascript
379
+ const item = $input.item;
380
+ const data = item.json;
381
+
382
+ // Process based on item type
383
+ if (data.type === 'premium') {
384
+ return [{
385
+ json: {
386
+ ...data,
387
+ discount: 0.20,
388
+ tier: 'premium'
389
+ }
390
+ }];
391
+ } else {
392
+ return [{
393
+ json: {
394
+ ...data,
395
+ discount: 0.05,
396
+ tier: 'standard'
397
+ }
398
+ }];
399
+ }
400
+ ```
401
+
402
+ ---
403
+
404
+ ## Pattern 4: $node - Reference Other Nodes
405
+
406
+ **Usage**: Less common, but powerful for specific scenarios
407
+
408
+ **When to use:**
409
+ - Need data from specific named node
410
+ - Combining data from multiple nodes
411
+ - Accessing metadata about workflow execution
412
+
413
+ ### Basic Usage
414
+
415
+ ```javascript
416
+ // Get output from specific node
417
+ const webhookData = $node["Webhook"].json;
418
+ const apiData = $node["HTTP Request"].json;
419
+
420
+ return [{
421
+ json: {
422
+ fromWebhook: webhookData,
423
+ fromAPI: apiData
424
+ }
425
+ }];
426
+ ```
427
+
428
+ ### Example 1: Combine Multiple Sources
429
+
430
+ ```javascript
431
+ // Reference multiple nodes
432
+ const webhook = $node["Webhook"].json;
433
+ const database = $node["Postgres"].json;
434
+ const api = $node["HTTP Request"].json;
435
+
436
+ return [{
437
+ json: {
438
+ combined: {
439
+ webhook: webhook.body,
440
+ dbRecords: database.length,
441
+ apiResponse: api.status
442
+ },
443
+ processedAt: new Date().toISOString()
444
+ }
445
+ }];
446
+ ```
447
+
448
+ ### Example 2: Compare Across Nodes
449
+
450
+ ```javascript
451
+ const oldData = $node["Get Old Data"].json;
452
+ const newData = $node["Get New Data"].json;
453
+
454
+ // Compare
455
+ const changes = {
456
+ added: newData.filter(n => !oldData.find(o => o.id === n.id)),
457
+ removed: oldData.filter(o => !newData.find(n => n.id === o.id)),
458
+ modified: newData.filter(n => {
459
+ const old = oldData.find(o => o.id === n.id);
460
+ return old && JSON.stringify(old) !== JSON.stringify(n);
461
+ })
462
+ };
463
+
464
+ return [{
465
+ json: {
466
+ changes,
467
+ summary: {
468
+ added: changes.added.length,
469
+ removed: changes.removed.length,
470
+ modified: changes.modified.length
471
+ }
472
+ }
473
+ }];
474
+ ```
475
+
476
+ ### Example 3: Access Node Metadata
477
+
478
+ ```javascript
479
+ // Get data from specific execution path
480
+ const ifTrueBranch = $node["IF True"].json;
481
+ const ifFalseBranch = $node["IF False"].json;
482
+
483
+ // Use whichever branch executed
484
+ const result = ifTrueBranch || ifFalseBranch || {};
485
+
486
+ return [{json: result}];
487
+ ```
488
+
489
+ ---
490
+
491
+ ## Critical: Webhook Data Structure
492
+
493
+ **MOST COMMON MISTAKE**: Forgetting webhook data is nested under `.body`
494
+
495
+ ### The Problem
496
+
497
+ Webhook node wraps all incoming data under a `body` property. This catches many developers by surprise.
498
+
499
+ ### Structure
500
+
501
+ ```javascript
502
+ // Webhook node output structure:
503
+ {
504
+ "headers": {
505
+ "content-type": "application/json",
506
+ "user-agent": "...",
507
+ // ... other headers
508
+ },
509
+ "params": {},
510
+ "query": {},
511
+ "body": {
512
+ // ← YOUR DATA IS HERE
513
+ "name": "Alice",
514
+ "email": "alice@example.com",
515
+ "message": "Hello!"
516
+ }
517
+ }
518
+ ```
519
+
520
+ ### Wrong vs Right
521
+
522
+ ```javascript
523
+ // ❌ WRONG: Trying to access directly
524
+ const name = $json.name; // undefined
525
+ const email = $json.email; // undefined
526
+
527
+ // ✅ CORRECT: Access via .body
528
+ const name = $json.body.name; // "Alice"
529
+ const email = $json.body.email; // "alice@example.com"
530
+
531
+ // ✅ CORRECT: Extract body first
532
+ const webhookData = $json.body;
533
+ const name = webhookData.name; // "Alice"
534
+ const email = webhookData.email; // "alice@example.com"
535
+ ```
536
+
537
+ ### Example: Full Webhook Processing
538
+
539
+ ```javascript
540
+ // Get webhook data from previous node
541
+ const webhookOutput = $input.first().json;
542
+
543
+ // Access the actual payload
544
+ const payload = webhookOutput.body;
545
+
546
+ // Access headers if needed
547
+ const contentType = webhookOutput.headers['content-type'];
548
+
549
+ // Access query parameters if needed
550
+ const apiKey = webhookOutput.query.api_key;
551
+
552
+ // Process the actual data
553
+ return [{
554
+ json: {
555
+ // Data from webhook body
556
+ userName: payload.name,
557
+ userEmail: payload.email,
558
+ message: payload.message,
559
+
560
+ // Metadata
561
+ receivedAt: new Date().toISOString(),
562
+ contentType: contentType,
563
+ authenticated: !!apiKey
564
+ }
565
+ }];
566
+ ```
567
+
568
+ ### POST Data, Query Params, and Headers
569
+
570
+ ```javascript
571
+ const webhook = $input.first().json;
572
+
573
+ return [{
574
+ json: {
575
+ // POST body data
576
+ formData: webhook.body,
577
+
578
+ // Query parameters (?key=value)
579
+ queryParams: webhook.query,
580
+
581
+ // HTTP headers
582
+ userAgent: webhook.headers['user-agent'],
583
+ contentType: webhook.headers['content-type'],
584
+
585
+ // Request metadata
586
+ method: webhook.method, // POST, GET, etc.
587
+ url: webhook.url
588
+ }
589
+ }];
590
+ ```
591
+
592
+ ### Common Webhook Scenarios
593
+
594
+ ```javascript
595
+ // Scenario 1: Form submission
596
+ const formData = $json.body;
597
+ const name = formData.name;
598
+ const email = formData.email;
599
+
600
+ // Scenario 2: JSON API webhook
601
+ const apiPayload = $json.body;
602
+ const eventType = apiPayload.event;
603
+ const data = apiPayload.data;
604
+
605
+ // Scenario 3: Query parameters
606
+ const apiKey = $json.query.api_key;
607
+ const userId = $json.query.user_id;
608
+
609
+ // Scenario 4: Headers
610
+ const authorization = $json.headers['authorization'];
611
+ const signature = $json.headers['x-signature'];
612
+ ```
613
+
614
+ ---
615
+
616
+ ## Choosing the Right Pattern
617
+
618
+ ### Decision Tree
619
+
620
+ ```
621
+ Do you need ALL items from previous node?
622
+ ├─ YES → Use $input.all()
623
+
624
+ └─ NO → Do you need just the FIRST item?
625
+ ├─ YES → Use $input.first()
626
+
627
+ └─ NO → Are you in "Each Item" mode?
628
+ ├─ YES → Use $input.item
629
+
630
+ └─ NO → Do you need specific node data?
631
+ ├─ YES → Use $node["NodeName"]
632
+ └─ NO → Use $input.first() (default)
633
+ ```
634
+
635
+ ### Quick Reference Table
636
+
637
+ | Scenario | Use This | Example |
638
+ |----------|----------|---------|
639
+ | Sum all amounts | `$input.all()` | `allItems.reduce((sum, i) => sum + i.json.amount, 0)` |
640
+ | Get API response | `$input.first()` | `$input.first().json.data` |
641
+ | Process each independently | `$input.item` | `$input.item.json` (Each Item mode) |
642
+ | Combine two nodes | `$node["Name"]` | `$node["API"].json` |
643
+ | Filter array | `$input.all()` | `allItems.filter(i => i.json.active)` |
644
+ | Transform single object | `$input.first()` | `{...input.first().json, new: true}` |
645
+ | Webhook data | `$input.first()` | `$input.first().json.body` |
646
+
647
+ ---
648
+
649
+ ## Common Mistakes
650
+
651
+ ### Mistake 1: Using $json Without Context
652
+
653
+ ```javascript
654
+ // ❌ WRONG: $json is ambiguous
655
+ const value = $json.field;
656
+
657
+ // ✅ CORRECT: Be explicit
658
+ const value = $input.first().json.field;
659
+ ```
660
+
661
+ ### Mistake 2: Forgetting .json Property
662
+
663
+ ```javascript
664
+ // ❌ WRONG: Trying to access fields on item object
665
+ const items = $input.all();
666
+ const names = items.map(item => item.name); // undefined
667
+
668
+ // ✅ CORRECT: Access via .json
669
+ const names = items.map(item => item.json.name);
670
+ ```
671
+
672
+ ### Mistake 3: Using $input.item in All Items Mode
673
+
674
+ ```javascript
675
+ // ❌ WRONG: $input.item is undefined in "All Items" mode
676
+ const data = $input.item.json; // Error!
677
+
678
+ // ✅ CORRECT: Use appropriate method
679
+ const data = $input.first().json; // Or $input.all()
680
+ ```
681
+
682
+ ### Mistake 4: Not Handling Empty Arrays
683
+
684
+ ```javascript
685
+ // ❌ WRONG: Crashes if no items
686
+ const first = $input.all()[0].json;
687
+
688
+ // ✅ CORRECT: Check length first
689
+ const items = $input.all();
690
+ if (items.length === 0) {
691
+ return [];
692
+ }
693
+ const first = items[0].json;
694
+
695
+ // ✅ ALSO CORRECT: Use $input.first()
696
+ const first = $input.first().json; // Built-in safety
697
+ ```
698
+
699
+ ### Mistake 5: Modifying Original Data
700
+
701
+ ```javascript
702
+ // ❌ RISKY: Mutating original
703
+ const items = $input.all();
704
+ items[0].json.modified = true; // Modifies original
705
+ return items;
706
+
707
+ // ✅ SAFE: Create new objects
708
+ const items = $input.all();
709
+ return items.map(item => ({
710
+ json: {
711
+ ...item.json,
712
+ modified: true
713
+ }
714
+ }));
715
+ ```
716
+
717
+ ---
718
+
719
+ ## Advanced Patterns
720
+
721
+ ### Pattern: Pagination Handling
722
+
723
+ ```javascript
724
+ const currentPage = $input.all();
725
+ const pageNumber = $node["Set Page"].json.page || 1;
726
+
727
+ // Combine with previous pages
728
+ const allPreviousPages = $node["Accumulator"]?.json.accumulated || [];
729
+
730
+ return [{
731
+ json: {
732
+ accumulated: [...allPreviousPages, ...currentPage],
733
+ currentPage: pageNumber,
734
+ totalItems: allPreviousPages.length + currentPage.length
735
+ }
736
+ }];
737
+ ```
738
+
739
+ ### Pattern: Conditional Node Reference
740
+
741
+ ```javascript
742
+ // Access different nodes based on condition
743
+ const condition = $input.first().json.type;
744
+
745
+ let data;
746
+ if (condition === 'api') {
747
+ data = $node["API Response"].json;
748
+ } else if (condition === 'database') {
749
+ data = $node["Database"].json;
750
+ } else {
751
+ data = $node["Default"].json;
752
+ }
753
+
754
+ return [{json: data}];
755
+ ```
756
+
757
+ ### Pattern: Multi-Node Aggregation
758
+
759
+ ```javascript
760
+ // Collect data from multiple named nodes
761
+ const sources = ['Source1', 'Source2', 'Source3'];
762
+ const allData = [];
763
+
764
+ for (const source of sources) {
765
+ const nodeData = $node[source]?.json;
766
+ if (nodeData) {
767
+ allData.push({
768
+ source,
769
+ data: nodeData
770
+ });
771
+ }
772
+ }
773
+
774
+ return allData.map(item => ({json: item}));
775
+ ```
776
+
777
+ ---
778
+
779
+ ## Summary
780
+
781
+ **Most Common Patterns**:
782
+ 1. `$input.all()` - Process multiple items, batch operations
783
+ 2. `$input.first()` - Single item, API responses
784
+ 3. `$input.item` - Each Item mode processing
785
+
786
+ **Critical Rule**:
787
+ - Webhook data is under `.body` property
788
+
789
+ **Best Practice**:
790
+ - Be explicit: Use `$input.first().json.field` instead of `$json.field`
791
+ - Always check for null/undefined
792
+ - Use appropriate method for your mode (All Items vs Each Item)
793
+
794
+ **See Also**:
795
+ - [SKILL.md](SKILL.md) - Overview and quick start
796
+ - [COMMON_PATTERNS.md](COMMON_PATTERNS.md) - Production patterns
797
+ - [ERROR_PATTERNS.md](ERROR_PATTERNS.md) - Avoid common mistakes