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