@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,779 @@
1
+ <!--
2
+ VENDORED from n8n-builder@d293559 (n8n-code-javascript/BUILTIN_FUNCTIONS.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
+ # Built-in Functions - JavaScript Code Node
15
+
16
+ Complete reference for n8n's built-in JavaScript functions and helpers.
17
+
18
+ ---
19
+
20
+ ## Overview
21
+
22
+ n8n Code nodes provide powerful built-in functions beyond standard JavaScript. This guide covers:
23
+
24
+ 1. **$helpers.httpRequest()** - Make HTTP requests (legacy in-process instances only — not defined under default n8n 2.x task runners; see warning in section 1)
25
+ 2. **DateTime (Luxon)** - Advanced date/time operations
26
+ 3. **$jmespath()** - Query JSON structures
27
+ 4. **$getWorkflowStaticData()** - Persistent storage
28
+ 5. **Standard JavaScript Globals** - Math, JSON, console, etc.
29
+ 6. **Available Node.js Modules** - crypto, Buffer, URL
30
+
31
+ ---
32
+
33
+ ## 1. $helpers.httpRequest() - HTTP Requests
34
+
35
+ > ⚠️ **n8n 2.0+ (task runners on by default): `$helpers` is unavailable in the Code node.** Since n8n 2.0 (Dec 2025), Code node executions run on task runners by default (`N8N_RUNNERS_ENABLED=true`), and the runner sandbox does **not** expose `$helpers`. `$helpers.httpRequest*` and `$helpers.getBinaryDataBuffer` throw `ReferenceError: $helpers is not defined`. The `$helpers` examples below only work on instances with task runners explicitly disabled (legacy/in-process mode). **On any default 2.x instance, use an HTTP Request node** (set `options.response.response.neverError: true` for fallback chains) instead of the patterns in this section. The behavior often passes in the "Execute Step" preview but fails on full execution — always test the whole workflow.
36
+
37
+ Make HTTP requests directly from Code nodes without using HTTP Request node.
38
+
39
+ ### Basic Usage
40
+
41
+ ```javascript
42
+ const response = await $helpers.httpRequest({
43
+ method: 'GET',
44
+ url: 'https://api.example.com/users'
45
+ });
46
+
47
+ return [{json: {data: response}}];
48
+ ```
49
+
50
+ ### Complete Options
51
+
52
+ ```javascript
53
+ const response = await $helpers.httpRequest({
54
+ method: 'POST', // GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS
55
+ url: 'https://api.example.com/users',
56
+ headers: {
57
+ 'Authorization': 'Bearer token123',
58
+ 'Content-Type': 'application/json',
59
+ 'User-Agent': 'n8n-workflow'
60
+ },
61
+ body: {
62
+ name: 'John Doe',
63
+ email: 'john@example.com'
64
+ },
65
+ qs: { // Query string parameters
66
+ page: 1,
67
+ limit: 10
68
+ },
69
+ timeout: 10000, // Milliseconds (default: no timeout)
70
+ json: true, // Auto-parse JSON response (default: true)
71
+ simple: false, // Don't throw on HTTP errors (default: true)
72
+ resolveWithFullResponse: false // Return only body (default: false)
73
+ });
74
+ ```
75
+
76
+ ### GET Request
77
+
78
+ ```javascript
79
+ // Simple GET
80
+ const users = await $helpers.httpRequest({
81
+ method: 'GET',
82
+ url: 'https://api.example.com/users'
83
+ });
84
+
85
+ return [{json: {users}}];
86
+ ```
87
+
88
+ ```javascript
89
+ // GET with query parameters
90
+ const results = await $helpers.httpRequest({
91
+ method: 'GET',
92
+ url: 'https://api.example.com/search',
93
+ qs: {
94
+ q: 'javascript',
95
+ page: 1,
96
+ per_page: 50
97
+ }
98
+ });
99
+
100
+ return [{json: results}];
101
+ ```
102
+
103
+ ### POST Request
104
+
105
+ ```javascript
106
+ // POST with JSON body
107
+ const newUser = await $helpers.httpRequest({
108
+ method: 'POST',
109
+ url: 'https://api.example.com/users',
110
+ headers: {
111
+ 'Content-Type': 'application/json',
112
+ 'Authorization': 'Bearer ' + $env.API_KEY
113
+ },
114
+ body: {
115
+ name: $json.body.name,
116
+ email: $json.body.email,
117
+ role: 'user'
118
+ }
119
+ });
120
+
121
+ return [{json: newUser}];
122
+ ```
123
+
124
+ ### PUT/PATCH Request
125
+
126
+ ```javascript
127
+ // Update resource
128
+ const updated = await $helpers.httpRequest({
129
+ method: 'PATCH',
130
+ url: `https://api.example.com/users/${userId}`,
131
+ body: {
132
+ name: 'Updated Name',
133
+ status: 'active'
134
+ }
135
+ });
136
+
137
+ return [{json: updated}];
138
+ ```
139
+
140
+ ### DELETE Request
141
+
142
+ ```javascript
143
+ // Delete resource
144
+ await $helpers.httpRequest({
145
+ method: 'DELETE',
146
+ url: `https://api.example.com/users/${userId}`,
147
+ headers: {
148
+ 'Authorization': 'Bearer ' + $env.API_KEY
149
+ }
150
+ });
151
+
152
+ return [{json: {deleted: true, userId}}];
153
+ ```
154
+
155
+ ### Authentication Patterns
156
+
157
+ ```javascript
158
+ // Bearer Token
159
+ const response = await $helpers.httpRequest({
160
+ url: 'https://api.example.com/data',
161
+ headers: {
162
+ 'Authorization': `Bearer ${$env.API_TOKEN}`
163
+ }
164
+ });
165
+ ```
166
+
167
+ ```javascript
168
+ // API Key in Header
169
+ const response = await $helpers.httpRequest({
170
+ url: 'https://api.example.com/data',
171
+ headers: {
172
+ 'X-API-Key': $env.API_KEY
173
+ }
174
+ });
175
+ ```
176
+
177
+ ```javascript
178
+ // Basic Auth (manual)
179
+ const credentials = Buffer.from(`${username}:${password}`).toString('base64');
180
+
181
+ const response = await $helpers.httpRequest({
182
+ url: 'https://api.example.com/data',
183
+ headers: {
184
+ 'Authorization': `Basic ${credentials}`
185
+ }
186
+ });
187
+ ```
188
+
189
+ ### Error Handling
190
+
191
+ ```javascript
192
+ // Handle HTTP errors gracefully
193
+ try {
194
+ const response = await $helpers.httpRequest({
195
+ method: 'GET',
196
+ url: 'https://api.example.com/users',
197
+ simple: false // Don't throw on 4xx/5xx
198
+ });
199
+
200
+ if (response.statusCode >= 200 && response.statusCode < 300) {
201
+ return [{json: {success: true, data: response.body}}];
202
+ } else {
203
+ return [{
204
+ json: {
205
+ success: false,
206
+ status: response.statusCode,
207
+ error: response.body
208
+ }
209
+ }];
210
+ }
211
+ } catch (error) {
212
+ return [{
213
+ json: {
214
+ success: false,
215
+ error: error.message
216
+ }
217
+ }];
218
+ }
219
+ ```
220
+
221
+ ### Full Response Access
222
+
223
+ ```javascript
224
+ // Get full response including headers and status
225
+ const response = await $helpers.httpRequest({
226
+ url: 'https://api.example.com/data',
227
+ resolveWithFullResponse: true
228
+ });
229
+
230
+ return [{
231
+ json: {
232
+ statusCode: response.statusCode,
233
+ headers: response.headers,
234
+ body: response.body,
235
+ rateLimit: response.headers['x-ratelimit-remaining']
236
+ }
237
+ }];
238
+ ```
239
+
240
+ ---
241
+
242
+ ## 2. DateTime (Luxon) - Date & Time Operations
243
+
244
+ n8n includes Luxon for powerful date/time handling. Access via `DateTime` global.
245
+
246
+ ### Current Date/Time
247
+
248
+ ```javascript
249
+ // Current time
250
+ const now = DateTime.now();
251
+
252
+ // Current time in specific timezone
253
+ const nowTokyo = DateTime.now().setZone('Asia/Tokyo');
254
+
255
+ // Today at midnight
256
+ const today = DateTime.now().startOf('day');
257
+
258
+ return [{
259
+ json: {
260
+ iso: now.toISO(), // "2025-01-20T15:30:00.000Z"
261
+ formatted: now.toFormat('yyyy-MM-dd HH:mm:ss'), // "2025-01-20 15:30:00"
262
+ unix: now.toSeconds(), // Unix timestamp
263
+ millis: now.toMillis() // Milliseconds since epoch
264
+ }
265
+ }];
266
+ ```
267
+
268
+ ### Formatting Dates
269
+
270
+ ```javascript
271
+ const now = DateTime.now();
272
+
273
+ return [{
274
+ json: {
275
+ isoFormat: now.toISO(), // ISO 8601: "2025-01-20T15:30:00.000Z"
276
+ sqlFormat: now.toSQL(), // SQL: "2025-01-20 15:30:00.000"
277
+ httpFormat: now.toHTTP(), // HTTP: "Mon, 20 Jan 2025 15:30:00 GMT"
278
+
279
+ // Custom formats
280
+ dateOnly: now.toFormat('yyyy-MM-dd'), // "2025-01-20"
281
+ timeOnly: now.toFormat('HH:mm:ss'), // "15:30:00"
282
+ readable: now.toFormat('MMMM dd, yyyy'), // "January 20, 2025"
283
+ compact: now.toFormat('yyyyMMdd'), // "20250120"
284
+ withDay: now.toFormat('EEEE, MMMM dd, yyyy'), // "Monday, January 20, 2025"
285
+ custom: now.toFormat('dd/MM/yy HH:mm') // "20/01/25 15:30"
286
+ }
287
+ }];
288
+ ```
289
+
290
+ ### Parsing Dates
291
+
292
+ ```javascript
293
+ // From ISO string
294
+ const dt1 = DateTime.fromISO('2025-01-20T15:30:00');
295
+
296
+ // From specific format
297
+ const dt2 = DateTime.fromFormat('01/20/2025', 'MM/dd/yyyy');
298
+
299
+ // From SQL
300
+ const dt3 = DateTime.fromSQL('2025-01-20 15:30:00');
301
+
302
+ // From Unix timestamp
303
+ const dt4 = DateTime.fromSeconds(1737384600);
304
+
305
+ // From milliseconds
306
+ const dt5 = DateTime.fromMillis(1737384600000);
307
+
308
+ return [{json: {parsed: dt1.toISO()}}];
309
+ ```
310
+
311
+ ### Date Arithmetic
312
+
313
+ ```javascript
314
+ const now = DateTime.now();
315
+
316
+ return [{
317
+ json: {
318
+ // Adding time
319
+ tomorrow: now.plus({days: 1}).toISO(),
320
+ nextWeek: now.plus({weeks: 1}).toISO(),
321
+ nextMonth: now.plus({months: 1}).toISO(),
322
+ inTwoHours: now.plus({hours: 2}).toISO(),
323
+
324
+ // Subtracting time
325
+ yesterday: now.minus({days: 1}).toISO(),
326
+ lastWeek: now.minus({weeks: 1}).toISO(),
327
+ lastMonth: now.minus({months: 1}).toISO(),
328
+ twoHoursAgo: now.minus({hours: 2}).toISO(),
329
+
330
+ // Complex operations
331
+ in90Days: now.plus({days: 90}).toFormat('yyyy-MM-dd'),
332
+ in6Months: now.plus({months: 6}).toFormat('yyyy-MM-dd')
333
+ }
334
+ }];
335
+ ```
336
+
337
+ ### Time Comparisons
338
+
339
+ ```javascript
340
+ const now = DateTime.now();
341
+ const targetDate = DateTime.fromISO('2025-12-31');
342
+
343
+ return [{
344
+ json: {
345
+ // Comparisons
346
+ isFuture: targetDate > now,
347
+ isPast: targetDate < now,
348
+ isEqual: targetDate.equals(now),
349
+
350
+ // Differences
351
+ daysUntil: targetDate.diff(now, 'days').days,
352
+ hoursUntil: targetDate.diff(now, 'hours').hours,
353
+ monthsUntil: targetDate.diff(now, 'months').months,
354
+
355
+ // Detailed difference
356
+ detailedDiff: targetDate.diff(now, ['months', 'days', 'hours']).toObject()
357
+ }
358
+ }];
359
+ ```
360
+
361
+ ### Timezone Operations
362
+
363
+ ```javascript
364
+ const now = DateTime.now();
365
+
366
+ return [{
367
+ json: {
368
+ // Current timezone
369
+ local: now.toISO(),
370
+
371
+ // Convert to different timezone
372
+ tokyo: now.setZone('Asia/Tokyo').toISO(),
373
+ newYork: now.setZone('America/New_York').toISO(),
374
+ london: now.setZone('Europe/London').toISO(),
375
+ utc: now.toUTC().toISO(),
376
+
377
+ // Get timezone info
378
+ timezone: now.zoneName, // "America/Los_Angeles"
379
+ offset: now.offset, // Offset in minutes
380
+ offsetFormatted: now.toFormat('ZZ') // "+08:00"
381
+ }
382
+ }];
383
+ ```
384
+
385
+ ### Start/End of Period
386
+
387
+ ```javascript
388
+ const now = DateTime.now();
389
+
390
+ return [{
391
+ json: {
392
+ startOfDay: now.startOf('day').toISO(),
393
+ endOfDay: now.endOf('day').toISO(),
394
+ startOfWeek: now.startOf('week').toISO(),
395
+ endOfWeek: now.endOf('week').toISO(),
396
+ startOfMonth: now.startOf('month').toISO(),
397
+ endOfMonth: now.endOf('month').toISO(),
398
+ startOfYear: now.startOf('year').toISO(),
399
+ endOfYear: now.endOf('year').toISO()
400
+ }
401
+ }];
402
+ ```
403
+
404
+ ### Weekday & Month Info
405
+
406
+ ```javascript
407
+ const now = DateTime.now();
408
+
409
+ return [{
410
+ json: {
411
+ // Day info
412
+ weekday: now.weekday, // 1 = Monday, 7 = Sunday
413
+ weekdayShort: now.weekdayShort, // "Mon"
414
+ weekdayLong: now.weekdayLong, // "Monday"
415
+ isWeekend: now.weekday > 5, // Saturday or Sunday
416
+
417
+ // Month info
418
+ month: now.month, // 1-12
419
+ monthShort: now.monthShort, // "Jan"
420
+ monthLong: now.monthLong, // "January"
421
+
422
+ // Year info
423
+ year: now.year, // 2025
424
+ quarter: now.quarter, // 1-4
425
+ daysInMonth: now.daysInMonth // 28-31
426
+ }
427
+ }];
428
+ ```
429
+
430
+ ---
431
+
432
+ ## 3. $jmespath() - JSON Querying
433
+
434
+ Query and transform JSON structures using JMESPath syntax.
435
+
436
+ ### Basic Queries
437
+
438
+ ```javascript
439
+ const data = $input.first().json;
440
+
441
+ // Extract specific field
442
+ const names = $jmespath(data, 'users[*].name');
443
+
444
+ // Filter array
445
+ const adults = $jmespath(data, 'users[?age >= `18`]');
446
+
447
+ // Get specific index
448
+ const firstUser = $jmespath(data, 'users[0]');
449
+
450
+ return [{json: {names, adults, firstUser}}];
451
+ ```
452
+
453
+ ### Advanced Queries
454
+
455
+ ```javascript
456
+ const data = $input.first().json;
457
+
458
+ // Sort and slice
459
+ const top5 = $jmespath(data, 'users | sort_by(@, &score) | reverse(@) | [0:5]');
460
+
461
+ // Extract nested fields
462
+ const emails = $jmespath(data, 'users[*].contact.email');
463
+
464
+ // Multi-field extraction
465
+ const simplified = $jmespath(data, 'users[*].{name: name, email: contact.email}');
466
+
467
+ // Conditional filtering
468
+ const premium = $jmespath(data, 'users[?subscription.tier == `premium`]');
469
+
470
+ return [{json: {top5, emails, simplified, premium}}];
471
+ ```
472
+
473
+ ### Common Patterns
474
+
475
+ ```javascript
476
+ // Pattern 1: Filter and project
477
+ const query1 = $jmespath(data, 'products[?price > `100`].{name: name, price: price}');
478
+
479
+ // Pattern 2: Aggregate functions
480
+ const query2 = $jmespath(data, 'sum(products[*].price)');
481
+ const query3 = $jmespath(data, 'max(products[*].price)');
482
+ const query4 = $jmespath(data, 'length(products)');
483
+
484
+ // Pattern 3: Nested filtering
485
+ const query5 = $jmespath(data, 'categories[*].products[?inStock == `true`]');
486
+
487
+ return [{json: {query1, query2, query3, query4, query5}}];
488
+ ```
489
+
490
+ ---
491
+
492
+ ## 4. $getWorkflowStaticData() - Persistent Storage
493
+
494
+ Store data that persists across workflow executions.
495
+
496
+ ### Basic Usage
497
+
498
+ ```javascript
499
+ // Get static data storage
500
+ const staticData = $getWorkflowStaticData();
501
+
502
+ // Initialize counter if doesn't exist
503
+ if (!staticData.counter) {
504
+ staticData.counter = 0;
505
+ }
506
+
507
+ // Increment counter
508
+ staticData.counter++;
509
+
510
+ return [{
511
+ json: {
512
+ executionCount: staticData.counter
513
+ }
514
+ }];
515
+ ```
516
+
517
+ ### Use Cases
518
+
519
+ ```javascript
520
+ // Use Case 1: Rate limiting
521
+ const staticData = $getWorkflowStaticData();
522
+ const now = Date.now();
523
+
524
+ if (!staticData.lastRun) {
525
+ staticData.lastRun = now;
526
+ staticData.runCount = 1;
527
+ } else {
528
+ const timeSinceLastRun = now - staticData.lastRun;
529
+
530
+ if (timeSinceLastRun < 60000) { // Less than 1 minute
531
+ return [{json: {error: 'Rate limit: wait 1 minute between runs'}}];
532
+ }
533
+
534
+ staticData.lastRun = now;
535
+ staticData.runCount++;
536
+ }
537
+
538
+ return [{json: {allowed: true, totalRuns: staticData.runCount}}];
539
+ ```
540
+
541
+ ```javascript
542
+ // Use Case 2: Tracking last processed ID
543
+ const staticData = $getWorkflowStaticData();
544
+ const currentItems = $input.all();
545
+
546
+ // Get last processed ID
547
+ const lastId = staticData.lastProcessedId || 0;
548
+
549
+ // Filter only new items
550
+ const newItems = currentItems.filter(item => item.json.id > lastId);
551
+
552
+ // Update last processed ID
553
+ if (newItems.length > 0) {
554
+ staticData.lastProcessedId = Math.max(...newItems.map(item => item.json.id));
555
+ }
556
+
557
+ return newItems;
558
+ ```
559
+
560
+ ```javascript
561
+ // Use Case 3: Accumulating results
562
+ const staticData = $getWorkflowStaticData();
563
+
564
+ if (!staticData.accumulated) {
565
+ staticData.accumulated = [];
566
+ }
567
+
568
+ // Add current items to accumulated list
569
+ const currentData = $input.all().map(item => item.json);
570
+ staticData.accumulated.push(...currentData);
571
+
572
+ return [{
573
+ json: {
574
+ currentBatch: currentData.length,
575
+ totalAccumulated: staticData.accumulated.length,
576
+ allData: staticData.accumulated
577
+ }
578
+ }];
579
+ ```
580
+
581
+ ---
582
+
583
+ ## 5. Standard JavaScript Globals
584
+
585
+ ### Math Object
586
+
587
+ ```javascript
588
+ return [{
589
+ json: {
590
+ // Rounding
591
+ rounded: Math.round(3.7), // 4
592
+ floor: Math.floor(3.7), // 3
593
+ ceil: Math.ceil(3.2), // 4
594
+
595
+ // Min/Max
596
+ max: Math.max(1, 5, 3, 9, 2), // 9
597
+ min: Math.min(1, 5, 3, 9, 2), // 1
598
+
599
+ // Random
600
+ random: Math.random(), // 0-1
601
+ randomInt: Math.floor(Math.random() * 100), // 0-99
602
+
603
+ // Other
604
+ abs: Math.abs(-5), // 5
605
+ sqrt: Math.sqrt(16), // 4
606
+ pow: Math.pow(2, 3) // 8
607
+ }
608
+ }];
609
+ ```
610
+
611
+ ### JSON Object
612
+
613
+ ```javascript
614
+ // Parse JSON string
615
+ const jsonString = '{"name": "John", "age": 30}';
616
+ const parsed = JSON.parse(jsonString);
617
+
618
+ // Stringify object
619
+ const obj = {name: "John", age: 30};
620
+ const stringified = JSON.stringify(obj);
621
+
622
+ // Pretty print
623
+ const pretty = JSON.stringify(obj, null, 2);
624
+
625
+ return [{json: {parsed, stringified, pretty}}];
626
+ ```
627
+
628
+ ### console Object
629
+
630
+ ```javascript
631
+ // Debug logging (appears in browser console, press F12)
632
+ console.log('Processing items:', $input.all().length);
633
+ console.log('First item:', $input.first().json);
634
+
635
+ // Other console methods
636
+ console.error('Error message');
637
+ console.warn('Warning message');
638
+ console.info('Info message');
639
+
640
+ // Continues to return data
641
+ return [{json: {processed: true}}];
642
+ ```
643
+
644
+ ### Object Methods
645
+
646
+ ```javascript
647
+ const obj = {name: "John", age: 30, city: "NYC"};
648
+
649
+ return [{
650
+ json: {
651
+ keys: Object.keys(obj), // ["name", "age", "city"]
652
+ values: Object.values(obj), // ["John", 30, "NYC"]
653
+ entries: Object.entries(obj), // [["name", "John"], ...]
654
+
655
+ // Check property
656
+ hasName: 'name' in obj, // true
657
+
658
+ // Merge objects
659
+ merged: Object.assign({}, obj, {country: "USA"})
660
+ }
661
+ }];
662
+ ```
663
+
664
+ ### Array Methods
665
+
666
+ ```javascript
667
+ const arr = [1, 2, 3, 4, 5];
668
+
669
+ return [{
670
+ json: {
671
+ mapped: arr.map(x => x * 2), // [2, 4, 6, 8, 10]
672
+ filtered: arr.filter(x => x > 2), // [3, 4, 5]
673
+ reduced: arr.reduce((sum, x) => sum + x, 0), // 15
674
+ some: arr.some(x => x > 3), // true
675
+ every: arr.every(x => x > 0), // true
676
+ find: arr.find(x => x > 3), // 4
677
+ includes: arr.includes(3), // true
678
+ joined: arr.join(', ') // "1, 2, 3, 4, 5"
679
+ }
680
+ }];
681
+ ```
682
+
683
+ ---
684
+
685
+ ## 6. Available Node.js Modules
686
+
687
+ ### crypto Module
688
+
689
+ ```javascript
690
+ const crypto = require('crypto');
691
+
692
+ // Hash functions
693
+ const hash = crypto.createHash('sha256')
694
+ .update('my secret text')
695
+ .digest('hex');
696
+
697
+ // MD5 hash
698
+ const md5 = crypto.createHash('md5')
699
+ .update('my text')
700
+ .digest('hex');
701
+
702
+ // Random values
703
+ const randomBytes = crypto.randomBytes(16).toString('hex');
704
+
705
+ return [{json: {hash, md5, randomBytes}}];
706
+ ```
707
+
708
+ ### Buffer (built-in)
709
+
710
+ ```javascript
711
+ // Base64 encoding
712
+ const encoded = Buffer.from('Hello World').toString('base64');
713
+
714
+ // Base64 decoding
715
+ const decoded = Buffer.from(encoded, 'base64').toString();
716
+
717
+ // Hex encoding
718
+ const hex = Buffer.from('Hello').toString('hex');
719
+
720
+ return [{json: {encoded, decoded, hex}}];
721
+ ```
722
+
723
+ ### URL / URLSearchParams
724
+
725
+ ```javascript
726
+ // Parse URL
727
+ const url = new URL('https://example.com/path?param1=value1&param2=value2');
728
+
729
+ // Build query string
730
+ const params = new URLSearchParams({
731
+ search: 'query',
732
+ page: 1,
733
+ limit: 10
734
+ });
735
+
736
+ return [{
737
+ json: {
738
+ host: url.host,
739
+ pathname: url.pathname,
740
+ search: url.search,
741
+ queryString: params.toString() // "search=query&page=1&limit=10"
742
+ }
743
+ }];
744
+ ```
745
+
746
+ ---
747
+
748
+ ## What's NOT Available
749
+
750
+ **External npm packages are NOT available:**
751
+ - ❌ axios
752
+ - ❌ lodash
753
+ - ❌ moment (use DateTime/Luxon instead)
754
+ - ❌ request
755
+ - ❌ Any other npm package
756
+
757
+ **Workaround**: Use an HTTP Request node for HTTP (on legacy in-process instances only, $helpers.httpRequest() also works — see the n8n 2.0 warning in section 1).
758
+
759
+ ---
760
+
761
+ ## Summary
762
+
763
+ **Most Useful Built-ins**:
764
+ 1. **DateTime** - Professional date/time handling
765
+ 2. **$jmespath()** - Complex JSON queries
766
+ 3. **Math, JSON, Object, Array** - Standard JavaScript utilities
767
+ 4. **$helpers.httpRequest()** - legacy in-process instances ONLY; unavailable under default n8n 2.x task runners (see section 1 warning)
768
+
769
+ **Common Patterns**:
770
+ - API calls: Use an HTTP Request node (n8n 2.x default; $helpers is not defined on task runners)
771
+ - Date operations: Use DateTime (Luxon)
772
+ - Data filtering: Use $jmespath() or JavaScript .filter()
773
+ - Persistent data: Use $getWorkflowStaticData()
774
+ - Hashing: Use crypto module
775
+
776
+ **See Also**:
777
+ - [SKILL.md](SKILL.md) - Overview
778
+ - [COMMON_PATTERNS.md](COMMON_PATTERNS.md) - Real usage examples
779
+ - [ERROR_PATTERNS.md](ERROR_PATTERNS.md) - Error prevention