@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.
- package/dist/index.js +204 -8
- package/package.json +2 -2
- package/skill/awesomate-app-builder/SKILL.md +5 -1
- package/skill/awesomate-credentials/SKILL.md +1 -1
- package/skill/awesomate-hosting/SKILL.md +50 -159
- package/skill/awesomate-hosting/references/connect-troubleshooting.md +77 -0
- package/skill/awesomate-hosting/references/multi-account.md +33 -0
- package/skill/awesomate-hosting/references/rest-fallback.md +30 -0
- package/skill/awesomate-hosting/scripts/bootstrap.mjs +27 -7
- package/skill/awesomate-n8n/SKILL.md +153 -147
- package/skill/awesomate-n8n/evals/ai-agent-build/graders/grader.md +31 -0
- package/skill/awesomate-n8n/evals/ai-agent-build/prompt.md +1 -0
- package/skill/awesomate-n8n/evals/build-form-email/graders/grader.md +30 -0
- package/skill/awesomate-n8n/evals/build-form-email/prompt.md +1 -0
- package/skill/awesomate-n8n/evals/datatable-dedupe/graders/grader.md +32 -0
- package/skill/awesomate-n8n/evals/datatable-dedupe/prompt.md +2 -0
- package/skill/awesomate-n8n/evals/diagnose-failure/graders/grader.md +27 -0
- package/skill/awesomate-n8n/evals/diagnose-failure/prompt.md +2 -0
- package/skill/awesomate-n8n/evals/essentials-upsell/graders/grader.md +27 -0
- package/skill/awesomate-n8n/evals/essentials-upsell/prompt.md +2 -0
- package/skill/awesomate-n8n/evals/live-change-promote/graders/grader.md +35 -0
- package/skill/awesomate-n8n/evals/live-change-promote/prompt.md +2 -0
- package/skill/awesomate-n8n/evals/possibilities-grounded/graders/grader.md +28 -0
- package/skill/awesomate-n8n/evals/possibilities-grounded/prompt.md +1 -0
- package/skill/awesomate-n8n/evals/validated-not-done/graders/grader.md +27 -0
- package/skill/awesomate-n8n/evals/validated-not-done/prompt.md +2 -0
- package/skill/awesomate-n8n/evals/vars-not-env/graders/grader.md +26 -0
- package/skill/awesomate-n8n/evals/vars-not-env/prompt.md +2 -0
- package/skill/awesomate-n8n/evals/webhook-body-fix/graders/grader.md +26 -0
- package/skill/awesomate-n8n/evals/webhook-body-fix/prompt.md +3 -0
- package/skill/awesomate-n8n/references/ai-agents.md +135 -0
- package/skill/awesomate-n8n/references/datatables.md +105 -0
- package/skill/awesomate-n8n/references/{node-recipes.md → platform-notes.md} +56 -7
- package/skill/awesomate-n8n/references/possibilities.md +83 -0
- package/skill/awesomate-n8n/references/testing-policy.md +115 -0
- package/skill/awesomate-n8n/references/troubleshooting.md +69 -0
- package/skill/awesomate-n8n/references/upgrade-loop.md +98 -0
- package/skill/awesomate-n8n/references/vendor/MANIFEST.json +26 -0
- package/skill/awesomate-n8n/references/vendor/code-node/BUILTIN_FUNCTIONS.md +779 -0
- package/skill/awesomate-n8n/references/vendor/code-node/COMMON_PATTERNS.md +1123 -0
- package/skill/awesomate-n8n/references/vendor/code-node/DATA_ACCESS.md +797 -0
- package/skill/awesomate-n8n/references/vendor/code-node/ERROR_PATTERNS.md +776 -0
- package/skill/awesomate-n8n/references/vendor/code-node/SKILL.md +703 -0
- package/skill/awesomate-n8n/references/vendor/expressions/COMMON_MISTAKES.md +406 -0
- package/skill/awesomate-n8n/references/vendor/expressions/EXAMPLES.md +496 -0
- package/skill/awesomate-n8n/references/vendor/expressions/SKILL.md +525 -0
- package/skill/awesomate-n8n/references/vendor/node-configuration/DEPENDENCIES.md +743 -0
- package/skill/awesomate-n8n/references/vendor/node-configuration/OPERATION_PATTERNS.md +926 -0
- package/skill/awesomate-n8n/references/vendor/node-configuration/SKILL.md +583 -0
- package/skill/awesomate-n8n/references/vendor/validation/ERROR_CATALOG.md +781 -0
- package/skill/awesomate-n8n/references/vendor/validation/FALSE_POSITIVES.md +695 -0
- package/skill/awesomate-n8n/references/vendor/validation/SKILL.md +414 -0
- package/skill/awesomate-n8n/references/vendor/workflow-patterns/SKILL.md +413 -0
- package/skill/awesomate-n8n/references/vendor/workflow-patterns/ai_agent_workflow.md +797 -0
- package/skill/awesomate-n8n/references/vendor/workflow-patterns/database_operations.md +798 -0
- package/skill/awesomate-n8n/references/vendor/workflow-patterns/http_api_integration.md +747 -0
- package/skill/awesomate-n8n/references/vendor/workflow-patterns/scheduled_tasks.md +786 -0
- 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¶m2=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
|