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