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,974 @@
|
|
|
1
|
+
# Standard Library Reference - Python Code Node
|
|
2
|
+
|
|
3
|
+
Complete guide to available Python standard library modules in n8n Code nodes.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## ⚠️ Critical Limitation
|
|
8
|
+
|
|
9
|
+
**NO EXTERNAL LIBRARIES AVAILABLE**
|
|
10
|
+
|
|
11
|
+
Python Code nodes in n8n have **ONLY** the Python standard library. No pip packages.
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
# ❌ NOT AVAILABLE - Will cause ModuleNotFoundError
|
|
15
|
+
import requests # No HTTP library!
|
|
16
|
+
import pandas # No data analysis!
|
|
17
|
+
import numpy # No numerical computing!
|
|
18
|
+
import bs4 # No web scraping!
|
|
19
|
+
import selenium # No browser automation!
|
|
20
|
+
import psycopg2 # No database drivers!
|
|
21
|
+
import pymongo # No MongoDB!
|
|
22
|
+
import sqlalchemy # No ORMs!
|
|
23
|
+
|
|
24
|
+
# ✅ AVAILABLE - Standard library only
|
|
25
|
+
import json
|
|
26
|
+
import datetime
|
|
27
|
+
import re
|
|
28
|
+
import base64
|
|
29
|
+
import hashlib
|
|
30
|
+
import urllib.parse
|
|
31
|
+
import urllib.request
|
|
32
|
+
import math
|
|
33
|
+
import random
|
|
34
|
+
import statistics
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**Recommendation**: Use **JavaScript** for 95% of use cases. JavaScript has more capabilities in n8n.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Available Modules
|
|
42
|
+
|
|
43
|
+
### Priority 1: Most Useful (Use These)
|
|
44
|
+
|
|
45
|
+
1. **json** - JSON parsing and generation
|
|
46
|
+
2. **datetime** - Date and time operations
|
|
47
|
+
3. **re** - Regular expressions
|
|
48
|
+
4. **base64** - Base64 encoding/decoding
|
|
49
|
+
5. **hashlib** - Hashing (MD5, SHA256, etc.)
|
|
50
|
+
6. **urllib.parse** - URL parsing and encoding
|
|
51
|
+
|
|
52
|
+
### Priority 2: Moderately Useful
|
|
53
|
+
|
|
54
|
+
7. **math** - Mathematical functions
|
|
55
|
+
8. **random** - Random number generation
|
|
56
|
+
9. **statistics** - Statistical functions
|
|
57
|
+
10. **collections** - Specialized data structures
|
|
58
|
+
|
|
59
|
+
### Priority 3: Occasionally Useful
|
|
60
|
+
|
|
61
|
+
11. **itertools** - Iterator tools
|
|
62
|
+
12. **functools** - Higher-order functions
|
|
63
|
+
13. **operator** - Standard operators as functions
|
|
64
|
+
14. **string** - String constants and templates
|
|
65
|
+
15. **textwrap** - Text wrapping utilities
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Module 1: json - JSON Operations
|
|
70
|
+
|
|
71
|
+
**Most common module** - Parse and generate JSON data.
|
|
72
|
+
|
|
73
|
+
### Parse JSON String
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
import json
|
|
77
|
+
|
|
78
|
+
# Parse JSON string to Python dict
|
|
79
|
+
json_string = '{"name": "Alice", "age": 30}'
|
|
80
|
+
data = json.loads(json_string)
|
|
81
|
+
|
|
82
|
+
return [{
|
|
83
|
+
"json": {
|
|
84
|
+
"name": data["name"],
|
|
85
|
+
"age": data["age"],
|
|
86
|
+
"parsed": True
|
|
87
|
+
}
|
|
88
|
+
}]
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Generate JSON String
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
import json
|
|
95
|
+
|
|
96
|
+
# Convert Python dict to JSON string
|
|
97
|
+
data = {
|
|
98
|
+
"users": [
|
|
99
|
+
{"id": 1, "name": "Alice"},
|
|
100
|
+
{"id": 2, "name": "Bob"}
|
|
101
|
+
],
|
|
102
|
+
"total": 2
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
json_string = json.dumps(data, indent=2)
|
|
106
|
+
|
|
107
|
+
return [{
|
|
108
|
+
"json": {
|
|
109
|
+
"json_output": json_string,
|
|
110
|
+
"length": len(json_string)
|
|
111
|
+
}
|
|
112
|
+
}]
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Handle JSON Errors
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
import json
|
|
119
|
+
|
|
120
|
+
webhook_data = _input.first()["json"]["body"]
|
|
121
|
+
json_string = webhook_data.get("data", "")
|
|
122
|
+
|
|
123
|
+
try:
|
|
124
|
+
parsed = json.loads(json_string)
|
|
125
|
+
status = "valid"
|
|
126
|
+
error = None
|
|
127
|
+
except json.JSONDecodeError as e:
|
|
128
|
+
parsed = None
|
|
129
|
+
status = "invalid"
|
|
130
|
+
error = str(e)
|
|
131
|
+
|
|
132
|
+
return [{
|
|
133
|
+
"json": {
|
|
134
|
+
"status": status,
|
|
135
|
+
"data": parsed,
|
|
136
|
+
"error": error
|
|
137
|
+
}
|
|
138
|
+
}]
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Pretty Print JSON
|
|
142
|
+
|
|
143
|
+
```python
|
|
144
|
+
import json
|
|
145
|
+
|
|
146
|
+
# Format JSON with indentation
|
|
147
|
+
data = _input.first()["json"]
|
|
148
|
+
|
|
149
|
+
pretty_json = json.dumps(data, indent=2, sort_keys=True)
|
|
150
|
+
|
|
151
|
+
return [{
|
|
152
|
+
"json": {
|
|
153
|
+
"formatted": pretty_json
|
|
154
|
+
}
|
|
155
|
+
}]
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Module 2: datetime - Date and Time
|
|
161
|
+
|
|
162
|
+
**Very common** - Date parsing, formatting, calculations.
|
|
163
|
+
|
|
164
|
+
### Current Date and Time
|
|
165
|
+
|
|
166
|
+
```python
|
|
167
|
+
from datetime import datetime
|
|
168
|
+
|
|
169
|
+
now = datetime.now()
|
|
170
|
+
|
|
171
|
+
return [{
|
|
172
|
+
"json": {
|
|
173
|
+
"timestamp": now.isoformat(),
|
|
174
|
+
"date": now.strftime("%Y-%m-%d"),
|
|
175
|
+
"time": now.strftime("%H:%M:%S"),
|
|
176
|
+
"formatted": now.strftime("%B %d, %Y at %I:%M %p")
|
|
177
|
+
}
|
|
178
|
+
}]
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### Parse Date String
|
|
182
|
+
|
|
183
|
+
```python
|
|
184
|
+
from datetime import datetime
|
|
185
|
+
|
|
186
|
+
date_string = "2025-01-15T14:30:00"
|
|
187
|
+
dt = datetime.fromisoformat(date_string)
|
|
188
|
+
|
|
189
|
+
return [{
|
|
190
|
+
"json": {
|
|
191
|
+
"year": dt.year,
|
|
192
|
+
"month": dt.month,
|
|
193
|
+
"day": dt.day,
|
|
194
|
+
"hour": dt.hour,
|
|
195
|
+
"weekday": dt.strftime("%A")
|
|
196
|
+
}
|
|
197
|
+
}]
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Date Calculations
|
|
201
|
+
|
|
202
|
+
```python
|
|
203
|
+
from datetime import datetime, timedelta
|
|
204
|
+
|
|
205
|
+
now = datetime.now()
|
|
206
|
+
|
|
207
|
+
# Calculate future/past dates
|
|
208
|
+
tomorrow = now + timedelta(days=1)
|
|
209
|
+
yesterday = now - timedelta(days=1)
|
|
210
|
+
next_week = now + timedelta(weeks=1)
|
|
211
|
+
one_hour_ago = now - timedelta(hours=1)
|
|
212
|
+
|
|
213
|
+
return [{
|
|
214
|
+
"json": {
|
|
215
|
+
"now": now.isoformat(),
|
|
216
|
+
"tomorrow": tomorrow.isoformat(),
|
|
217
|
+
"yesterday": yesterday.isoformat(),
|
|
218
|
+
"next_week": next_week.isoformat(),
|
|
219
|
+
"one_hour_ago": one_hour_ago.isoformat()
|
|
220
|
+
}
|
|
221
|
+
}]
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Compare Dates
|
|
225
|
+
|
|
226
|
+
```python
|
|
227
|
+
from datetime import datetime
|
|
228
|
+
|
|
229
|
+
date1 = datetime(2025, 1, 15)
|
|
230
|
+
date2 = datetime(2025, 1, 20)
|
|
231
|
+
|
|
232
|
+
# Calculate difference
|
|
233
|
+
diff = date2 - date1
|
|
234
|
+
|
|
235
|
+
return [{
|
|
236
|
+
"json": {
|
|
237
|
+
"days_difference": diff.days,
|
|
238
|
+
"seconds_difference": diff.total_seconds(),
|
|
239
|
+
"date1_is_earlier": date1 < date2,
|
|
240
|
+
"date2_is_later": date2 > date1
|
|
241
|
+
}
|
|
242
|
+
}]
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Format Dates
|
|
246
|
+
|
|
247
|
+
```python
|
|
248
|
+
from datetime import datetime
|
|
249
|
+
|
|
250
|
+
dt = datetime.now()
|
|
251
|
+
|
|
252
|
+
return [{
|
|
253
|
+
"json": {
|
|
254
|
+
"iso": dt.isoformat(),
|
|
255
|
+
"us_format": dt.strftime("%m/%d/%Y"),
|
|
256
|
+
"eu_format": dt.strftime("%d/%m/%Y"),
|
|
257
|
+
"long_format": dt.strftime("%A, %B %d, %Y"),
|
|
258
|
+
"time_12h": dt.strftime("%I:%M %p"),
|
|
259
|
+
"time_24h": dt.strftime("%H:%M:%S")
|
|
260
|
+
}
|
|
261
|
+
}]
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
## Module 3: re - Regular Expressions
|
|
267
|
+
|
|
268
|
+
**Common** - Pattern matching, text extraction, validation.
|
|
269
|
+
|
|
270
|
+
### Pattern Matching
|
|
271
|
+
|
|
272
|
+
```python
|
|
273
|
+
import re
|
|
274
|
+
|
|
275
|
+
text = "Email: alice@example.com, Phone: 555-1234"
|
|
276
|
+
|
|
277
|
+
# Find email
|
|
278
|
+
email_match = re.search(r'\b[\w.-]+@[\w.-]+\.\w+\b', text)
|
|
279
|
+
email = email_match.group(0) if email_match else None
|
|
280
|
+
|
|
281
|
+
# Find phone
|
|
282
|
+
phone_match = re.search(r'\d{3}-\d{4}', text)
|
|
283
|
+
phone = phone_match.group(0) if phone_match else None
|
|
284
|
+
|
|
285
|
+
return [{
|
|
286
|
+
"json": {
|
|
287
|
+
"email": email,
|
|
288
|
+
"phone": phone
|
|
289
|
+
}
|
|
290
|
+
}]
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### Extract All Matches
|
|
294
|
+
|
|
295
|
+
```python
|
|
296
|
+
import re
|
|
297
|
+
|
|
298
|
+
text = "Tags: #python #automation #workflow #n8n"
|
|
299
|
+
|
|
300
|
+
# Find all hashtags
|
|
301
|
+
hashtags = re.findall(r'#(\w+)', text)
|
|
302
|
+
|
|
303
|
+
return [{
|
|
304
|
+
"json": {
|
|
305
|
+
"tags": hashtags,
|
|
306
|
+
"count": len(hashtags)
|
|
307
|
+
}
|
|
308
|
+
}]
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### Replace Patterns
|
|
312
|
+
|
|
313
|
+
```python
|
|
314
|
+
import re
|
|
315
|
+
|
|
316
|
+
text = "Price: $99.99, Discount: $10.00"
|
|
317
|
+
|
|
318
|
+
# Remove dollar signs
|
|
319
|
+
cleaned = re.sub(r'\$', '', text)
|
|
320
|
+
|
|
321
|
+
# Replace multiple spaces with single space
|
|
322
|
+
normalized = re.sub(r'\s+', ' ', cleaned)
|
|
323
|
+
|
|
324
|
+
return [{
|
|
325
|
+
"json": {
|
|
326
|
+
"original": text,
|
|
327
|
+
"cleaned": cleaned,
|
|
328
|
+
"normalized": normalized
|
|
329
|
+
}
|
|
330
|
+
}]
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### Validate Format
|
|
334
|
+
|
|
335
|
+
```python
|
|
336
|
+
import re
|
|
337
|
+
|
|
338
|
+
email = _input.first()["json"]["body"].get("email", "")
|
|
339
|
+
|
|
340
|
+
# Email validation pattern
|
|
341
|
+
email_pattern = r'^[\w.-]+@[\w.-]+\.\w+$'
|
|
342
|
+
is_valid = bool(re.match(email_pattern, email))
|
|
343
|
+
|
|
344
|
+
return [{
|
|
345
|
+
"json": {
|
|
346
|
+
"email": email,
|
|
347
|
+
"valid": is_valid
|
|
348
|
+
}
|
|
349
|
+
}]
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
### Split on Pattern
|
|
353
|
+
|
|
354
|
+
```python
|
|
355
|
+
import re
|
|
356
|
+
|
|
357
|
+
text = "apple,banana;orange|grape"
|
|
358
|
+
|
|
359
|
+
# Split on multiple delimiters
|
|
360
|
+
items = re.split(r'[,;|]', text)
|
|
361
|
+
|
|
362
|
+
# Clean up whitespace
|
|
363
|
+
items = [item.strip() for item in items]
|
|
364
|
+
|
|
365
|
+
return [{
|
|
366
|
+
"json": {
|
|
367
|
+
"items": items,
|
|
368
|
+
"count": len(items)
|
|
369
|
+
}
|
|
370
|
+
}]
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
---
|
|
374
|
+
|
|
375
|
+
## Module 4: base64 - Encoding/Decoding
|
|
376
|
+
|
|
377
|
+
**Common** - Encode binary data, API authentication.
|
|
378
|
+
|
|
379
|
+
### Encode String to Base64
|
|
380
|
+
|
|
381
|
+
```python
|
|
382
|
+
import base64
|
|
383
|
+
|
|
384
|
+
text = "Hello, World!"
|
|
385
|
+
|
|
386
|
+
# Encode to base64
|
|
387
|
+
encoded_bytes = base64.b64encode(text.encode('utf-8'))
|
|
388
|
+
encoded_string = encoded_bytes.decode('utf-8')
|
|
389
|
+
|
|
390
|
+
return [{
|
|
391
|
+
"json": {
|
|
392
|
+
"original": text,
|
|
393
|
+
"encoded": encoded_string
|
|
394
|
+
}
|
|
395
|
+
}]
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
### Decode Base64 to String
|
|
399
|
+
|
|
400
|
+
```python
|
|
401
|
+
import base64
|
|
402
|
+
|
|
403
|
+
encoded = "SGVsbG8sIFdvcmxkIQ=="
|
|
404
|
+
|
|
405
|
+
# Decode from base64
|
|
406
|
+
decoded_bytes = base64.b64decode(encoded)
|
|
407
|
+
decoded_string = decoded_bytes.decode('utf-8')
|
|
408
|
+
|
|
409
|
+
return [{
|
|
410
|
+
"json": {
|
|
411
|
+
"encoded": encoded,
|
|
412
|
+
"decoded": decoded_string
|
|
413
|
+
}
|
|
414
|
+
}]
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
### Basic Auth Header
|
|
418
|
+
|
|
419
|
+
```python
|
|
420
|
+
import base64
|
|
421
|
+
|
|
422
|
+
username = "admin"
|
|
423
|
+
password = "secret123"
|
|
424
|
+
|
|
425
|
+
# Create Basic Auth header
|
|
426
|
+
credentials = f"{username}:{password}"
|
|
427
|
+
encoded = base64.b64encode(credentials.encode('utf-8')).decode('utf-8')
|
|
428
|
+
auth_header = f"Basic {encoded}"
|
|
429
|
+
|
|
430
|
+
return [{
|
|
431
|
+
"json": {
|
|
432
|
+
"authorization": auth_header
|
|
433
|
+
}
|
|
434
|
+
}]
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
---
|
|
438
|
+
|
|
439
|
+
## Module 5: hashlib - Hashing
|
|
440
|
+
|
|
441
|
+
**Common** - Generate checksums, hash passwords, create IDs.
|
|
442
|
+
|
|
443
|
+
### MD5 Hash
|
|
444
|
+
|
|
445
|
+
```python
|
|
446
|
+
import hashlib
|
|
447
|
+
|
|
448
|
+
text = "Hello, World!"
|
|
449
|
+
|
|
450
|
+
# Generate MD5 hash
|
|
451
|
+
md5_hash = hashlib.md5(text.encode('utf-8')).hexdigest()
|
|
452
|
+
|
|
453
|
+
return [{
|
|
454
|
+
"json": {
|
|
455
|
+
"original": text,
|
|
456
|
+
"md5": md5_hash
|
|
457
|
+
}
|
|
458
|
+
}]
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
### SHA256 Hash
|
|
462
|
+
|
|
463
|
+
```python
|
|
464
|
+
import hashlib
|
|
465
|
+
|
|
466
|
+
data = _input.first()["json"]["body"]
|
|
467
|
+
text = data.get("password", "")
|
|
468
|
+
|
|
469
|
+
# Generate SHA256 hash (more secure than MD5)
|
|
470
|
+
sha256_hash = hashlib.sha256(text.encode('utf-8')).hexdigest()
|
|
471
|
+
|
|
472
|
+
return [{
|
|
473
|
+
"json": {
|
|
474
|
+
"hashed": sha256_hash
|
|
475
|
+
}
|
|
476
|
+
}]
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
### Generate Unique ID
|
|
480
|
+
|
|
481
|
+
```python
|
|
482
|
+
import hashlib
|
|
483
|
+
from datetime import datetime
|
|
484
|
+
|
|
485
|
+
# Create unique ID from multiple values
|
|
486
|
+
unique_string = f"{datetime.now().isoformat()}-{_json.get('user_id', 'unknown')}"
|
|
487
|
+
unique_id = hashlib.sha256(unique_string.encode('utf-8')).hexdigest()[:16]
|
|
488
|
+
|
|
489
|
+
return [{
|
|
490
|
+
"json": {
|
|
491
|
+
"id": unique_id,
|
|
492
|
+
"generated_at": datetime.now().isoformat()
|
|
493
|
+
}
|
|
494
|
+
}]
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
---
|
|
498
|
+
|
|
499
|
+
## Module 6: urllib.parse - URL Operations
|
|
500
|
+
|
|
501
|
+
**Common** - Parse URLs, encode parameters.
|
|
502
|
+
|
|
503
|
+
### Parse URL
|
|
504
|
+
|
|
505
|
+
```python
|
|
506
|
+
from urllib.parse import urlparse
|
|
507
|
+
|
|
508
|
+
url = "https://example.com/path?key=value&foo=bar#section"
|
|
509
|
+
|
|
510
|
+
parsed = urlparse(url)
|
|
511
|
+
|
|
512
|
+
return [{
|
|
513
|
+
"json": {
|
|
514
|
+
"scheme": parsed.scheme, # "https"
|
|
515
|
+
"netloc": parsed.netloc, # "example.com"
|
|
516
|
+
"path": parsed.path, # "/path"
|
|
517
|
+
"query": parsed.query, # "key=value&foo=bar"
|
|
518
|
+
"fragment": parsed.fragment # "section"
|
|
519
|
+
}
|
|
520
|
+
}]
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
### URL Encode Parameters
|
|
524
|
+
|
|
525
|
+
```python
|
|
526
|
+
from urllib.parse import urlencode
|
|
527
|
+
|
|
528
|
+
params = {
|
|
529
|
+
"name": "Alice Smith",
|
|
530
|
+
"email": "alice@example.com",
|
|
531
|
+
"message": "Hello, World!"
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
# Encode parameters for URL
|
|
535
|
+
encoded = urlencode(params)
|
|
536
|
+
|
|
537
|
+
return [{
|
|
538
|
+
"json": {
|
|
539
|
+
"query_string": encoded,
|
|
540
|
+
"full_url": f"https://api.example.com/submit?{encoded}"
|
|
541
|
+
}
|
|
542
|
+
}]
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
### Parse Query String
|
|
546
|
+
|
|
547
|
+
```python
|
|
548
|
+
from urllib.parse import parse_qs
|
|
549
|
+
|
|
550
|
+
query_string = "name=Alice&age=30&tags=python&tags=n8n"
|
|
551
|
+
|
|
552
|
+
# Parse query string
|
|
553
|
+
params = parse_qs(query_string)
|
|
554
|
+
|
|
555
|
+
return [{
|
|
556
|
+
"json": {
|
|
557
|
+
"name": params.get("name", [""])[0],
|
|
558
|
+
"age": int(params.get("age", ["0"])[0]),
|
|
559
|
+
"tags": params.get("tags", [])
|
|
560
|
+
}
|
|
561
|
+
}]
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
### URL Encode/Decode Strings
|
|
565
|
+
|
|
566
|
+
```python
|
|
567
|
+
from urllib.parse import quote, unquote
|
|
568
|
+
|
|
569
|
+
text = "Hello, World! 你好"
|
|
570
|
+
|
|
571
|
+
# URL encode
|
|
572
|
+
encoded = quote(text)
|
|
573
|
+
|
|
574
|
+
# URL decode
|
|
575
|
+
decoded = unquote(encoded)
|
|
576
|
+
|
|
577
|
+
return [{
|
|
578
|
+
"json": {
|
|
579
|
+
"original": text,
|
|
580
|
+
"encoded": encoded,
|
|
581
|
+
"decoded": decoded
|
|
582
|
+
}
|
|
583
|
+
}]
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
---
|
|
587
|
+
|
|
588
|
+
## Module 7: math - Mathematical Operations
|
|
589
|
+
|
|
590
|
+
**Moderately useful** - Advanced math functions.
|
|
591
|
+
|
|
592
|
+
### Basic Math Functions
|
|
593
|
+
|
|
594
|
+
```python
|
|
595
|
+
import math
|
|
596
|
+
|
|
597
|
+
number = 16.7
|
|
598
|
+
|
|
599
|
+
return [{
|
|
600
|
+
"json": {
|
|
601
|
+
"ceiling": math.ceil(number), # 17
|
|
602
|
+
"floor": math.floor(number), # 16
|
|
603
|
+
"rounded": round(number), # 17
|
|
604
|
+
"square_root": math.sqrt(16), # 4.0
|
|
605
|
+
"power": math.pow(2, 3), # 8.0
|
|
606
|
+
"absolute": math.fabs(-5.5) # 5.5
|
|
607
|
+
}
|
|
608
|
+
}]
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
### Trigonometry
|
|
612
|
+
|
|
613
|
+
```python
|
|
614
|
+
import math
|
|
615
|
+
|
|
616
|
+
angle_degrees = 45
|
|
617
|
+
angle_radians = math.radians(angle_degrees)
|
|
618
|
+
|
|
619
|
+
return [{
|
|
620
|
+
"json": {
|
|
621
|
+
"sine": math.sin(angle_radians),
|
|
622
|
+
"cosine": math.cos(angle_radians),
|
|
623
|
+
"tangent": math.tan(angle_radians),
|
|
624
|
+
"pi": math.pi,
|
|
625
|
+
"e": math.e
|
|
626
|
+
}
|
|
627
|
+
}]
|
|
628
|
+
```
|
|
629
|
+
|
|
630
|
+
### Logarithms
|
|
631
|
+
|
|
632
|
+
```python
|
|
633
|
+
import math
|
|
634
|
+
|
|
635
|
+
number = 100
|
|
636
|
+
|
|
637
|
+
return [{
|
|
638
|
+
"json": {
|
|
639
|
+
"log10": math.log10(number), # 2.0
|
|
640
|
+
"natural_log": math.log(number), # 4.605...
|
|
641
|
+
"log2": math.log2(number) # 6.644...
|
|
642
|
+
}
|
|
643
|
+
}]
|
|
644
|
+
```
|
|
645
|
+
|
|
646
|
+
---
|
|
647
|
+
|
|
648
|
+
## Module 8: random - Random Numbers
|
|
649
|
+
|
|
650
|
+
**Moderately useful** - Generate random data, sampling.
|
|
651
|
+
|
|
652
|
+
### Random Numbers
|
|
653
|
+
|
|
654
|
+
```python
|
|
655
|
+
import random
|
|
656
|
+
|
|
657
|
+
return [{
|
|
658
|
+
"json": {
|
|
659
|
+
"random_float": random.random(), # 0.0 to 1.0
|
|
660
|
+
"random_int": random.randint(1, 100), # 1 to 100
|
|
661
|
+
"random_range": random.randrange(0, 100, 5) # 0, 5, 10, ..., 95
|
|
662
|
+
}
|
|
663
|
+
}]
|
|
664
|
+
```
|
|
665
|
+
|
|
666
|
+
### Random Choice
|
|
667
|
+
|
|
668
|
+
```python
|
|
669
|
+
import random
|
|
670
|
+
|
|
671
|
+
colors = ["red", "green", "blue", "yellow"]
|
|
672
|
+
users = [{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}]
|
|
673
|
+
|
|
674
|
+
return [{
|
|
675
|
+
"json": {
|
|
676
|
+
"random_color": random.choice(colors),
|
|
677
|
+
"random_user": random.choice(users)
|
|
678
|
+
}
|
|
679
|
+
}]
|
|
680
|
+
```
|
|
681
|
+
|
|
682
|
+
### Shuffle List
|
|
683
|
+
|
|
684
|
+
```python
|
|
685
|
+
import random
|
|
686
|
+
|
|
687
|
+
items = [1, 2, 3, 4, 5]
|
|
688
|
+
shuffled = items.copy()
|
|
689
|
+
random.shuffle(shuffled)
|
|
690
|
+
|
|
691
|
+
return [{
|
|
692
|
+
"json": {
|
|
693
|
+
"original": items,
|
|
694
|
+
"shuffled": shuffled
|
|
695
|
+
}
|
|
696
|
+
}]
|
|
697
|
+
```
|
|
698
|
+
|
|
699
|
+
### Random Sample
|
|
700
|
+
|
|
701
|
+
```python
|
|
702
|
+
import random
|
|
703
|
+
|
|
704
|
+
items = list(range(1, 101))
|
|
705
|
+
|
|
706
|
+
# Get 10 random items without replacement
|
|
707
|
+
sample = random.sample(items, 10)
|
|
708
|
+
|
|
709
|
+
return [{
|
|
710
|
+
"json": {
|
|
711
|
+
"sample": sample,
|
|
712
|
+
"count": len(sample)
|
|
713
|
+
}
|
|
714
|
+
}]
|
|
715
|
+
```
|
|
716
|
+
|
|
717
|
+
---
|
|
718
|
+
|
|
719
|
+
## Module 9: statistics - Statistical Functions
|
|
720
|
+
|
|
721
|
+
**Moderately useful** - Calculate stats from data.
|
|
722
|
+
|
|
723
|
+
### Basic Statistics
|
|
724
|
+
|
|
725
|
+
```python
|
|
726
|
+
import statistics
|
|
727
|
+
|
|
728
|
+
numbers = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
|
|
729
|
+
|
|
730
|
+
return [{
|
|
731
|
+
"json": {
|
|
732
|
+
"mean": statistics.mean(numbers), # 55.0
|
|
733
|
+
"median": statistics.median(numbers), # 55.0
|
|
734
|
+
"mode": statistics.mode([1, 2, 2, 3]), # 2
|
|
735
|
+
"stdev": statistics.stdev(numbers), # 30.28...
|
|
736
|
+
"variance": statistics.variance(numbers) # 916.67...
|
|
737
|
+
}
|
|
738
|
+
}]
|
|
739
|
+
```
|
|
740
|
+
|
|
741
|
+
### Aggregate from Items
|
|
742
|
+
|
|
743
|
+
```python
|
|
744
|
+
import statistics
|
|
745
|
+
|
|
746
|
+
all_items = _input.all()
|
|
747
|
+
|
|
748
|
+
# Extract amounts
|
|
749
|
+
amounts = [item["json"].get("amount", 0) for item in all_items]
|
|
750
|
+
|
|
751
|
+
if amounts:
|
|
752
|
+
return [{
|
|
753
|
+
"json": {
|
|
754
|
+
"count": len(amounts),
|
|
755
|
+
"total": sum(amounts),
|
|
756
|
+
"average": statistics.mean(amounts),
|
|
757
|
+
"median": statistics.median(amounts),
|
|
758
|
+
"min": min(amounts),
|
|
759
|
+
"max": max(amounts),
|
|
760
|
+
"range": max(amounts) - min(amounts)
|
|
761
|
+
}
|
|
762
|
+
}]
|
|
763
|
+
else:
|
|
764
|
+
return [{"json": {"error": "No data"}}]
|
|
765
|
+
```
|
|
766
|
+
|
|
767
|
+
---
|
|
768
|
+
|
|
769
|
+
## Workarounds for Missing Libraries
|
|
770
|
+
|
|
771
|
+
### HTTP Requests (No requests library)
|
|
772
|
+
|
|
773
|
+
```python
|
|
774
|
+
# ❌ Can't use requests library
|
|
775
|
+
# import requests # ModuleNotFoundError!
|
|
776
|
+
|
|
777
|
+
# ✅ Use HTTP Request node instead
|
|
778
|
+
# Add HTTP Request node BEFORE Code node
|
|
779
|
+
# Access the response in Code node
|
|
780
|
+
|
|
781
|
+
response_data = _input.first()["json"]
|
|
782
|
+
|
|
783
|
+
return [{
|
|
784
|
+
"json": {
|
|
785
|
+
"status": response_data.get("status"),
|
|
786
|
+
"data": response_data.get("body"),
|
|
787
|
+
"processed": True
|
|
788
|
+
}
|
|
789
|
+
}]
|
|
790
|
+
```
|
|
791
|
+
|
|
792
|
+
### Data Processing (No pandas)
|
|
793
|
+
|
|
794
|
+
```python
|
|
795
|
+
# ❌ Can't use pandas
|
|
796
|
+
# import pandas as pd # ModuleNotFoundError!
|
|
797
|
+
|
|
798
|
+
# ✅ Use Python's built-in list comprehensions
|
|
799
|
+
all_items = _input.all()
|
|
800
|
+
|
|
801
|
+
# Filter
|
|
802
|
+
active_items = [
|
|
803
|
+
item for item in all_items
|
|
804
|
+
if item["json"].get("status") == "active"
|
|
805
|
+
]
|
|
806
|
+
|
|
807
|
+
# Group by
|
|
808
|
+
from collections import defaultdict
|
|
809
|
+
grouped = defaultdict(list)
|
|
810
|
+
|
|
811
|
+
for item in all_items:
|
|
812
|
+
category = item["json"].get("category", "other")
|
|
813
|
+
grouped[category].append(item["json"])
|
|
814
|
+
|
|
815
|
+
# Aggregate
|
|
816
|
+
import statistics
|
|
817
|
+
amounts = [item["json"].get("amount", 0) for item in all_items]
|
|
818
|
+
total = sum(amounts)
|
|
819
|
+
average = statistics.mean(amounts) if amounts else 0
|
|
820
|
+
|
|
821
|
+
return [{
|
|
822
|
+
"json": {
|
|
823
|
+
"active_count": len(active_items),
|
|
824
|
+
"grouped": dict(grouped),
|
|
825
|
+
"total": total,
|
|
826
|
+
"average": average
|
|
827
|
+
}
|
|
828
|
+
}]
|
|
829
|
+
```
|
|
830
|
+
|
|
831
|
+
### Database Operations (No drivers)
|
|
832
|
+
|
|
833
|
+
```python
|
|
834
|
+
# ❌ Can't use database drivers
|
|
835
|
+
# import psycopg2 # ModuleNotFoundError!
|
|
836
|
+
# import pymongo # ModuleNotFoundError!
|
|
837
|
+
|
|
838
|
+
# ✅ Use n8n database nodes instead
|
|
839
|
+
# Add Postgres/MySQL/MongoDB node BEFORE Code node
|
|
840
|
+
# Process results in Code node
|
|
841
|
+
|
|
842
|
+
db_results = _input.first()["json"]
|
|
843
|
+
|
|
844
|
+
return [{
|
|
845
|
+
"json": {
|
|
846
|
+
"record_count": len(db_results) if isinstance(db_results, list) else 1,
|
|
847
|
+
"processed": True
|
|
848
|
+
}
|
|
849
|
+
}]
|
|
850
|
+
```
|
|
851
|
+
|
|
852
|
+
---
|
|
853
|
+
|
|
854
|
+
## Complete Standard Library List
|
|
855
|
+
|
|
856
|
+
**Available** (commonly useful):
|
|
857
|
+
- json
|
|
858
|
+
- datetime, time
|
|
859
|
+
- re
|
|
860
|
+
- base64
|
|
861
|
+
- hashlib
|
|
862
|
+
- urllib.parse, urllib.request, urllib.error
|
|
863
|
+
- math
|
|
864
|
+
- random
|
|
865
|
+
- statistics
|
|
866
|
+
- collections (defaultdict, Counter, namedtuple)
|
|
867
|
+
- itertools
|
|
868
|
+
- functools
|
|
869
|
+
- operator
|
|
870
|
+
- string
|
|
871
|
+
- textwrap
|
|
872
|
+
|
|
873
|
+
**Available** (less common):
|
|
874
|
+
- os.path (path operations only)
|
|
875
|
+
- copy
|
|
876
|
+
- typing
|
|
877
|
+
- enum
|
|
878
|
+
- decimal
|
|
879
|
+
- fractions
|
|
880
|
+
|
|
881
|
+
**NOT Available** (external libraries):
|
|
882
|
+
- requests (HTTP)
|
|
883
|
+
- pandas (data analysis)
|
|
884
|
+
- numpy (numerical computing)
|
|
885
|
+
- bs4/beautifulsoup4 (HTML parsing)
|
|
886
|
+
- selenium (browser automation)
|
|
887
|
+
- psycopg2, pymongo, sqlalchemy (databases)
|
|
888
|
+
- flask, fastapi (web frameworks)
|
|
889
|
+
- pillow (image processing)
|
|
890
|
+
- openpyxl, xlsxwriter (Excel)
|
|
891
|
+
|
|
892
|
+
---
|
|
893
|
+
|
|
894
|
+
## Best Practices
|
|
895
|
+
|
|
896
|
+
### 1. Use Standard Library When Possible
|
|
897
|
+
|
|
898
|
+
```python
|
|
899
|
+
# ✅ GOOD: Use standard library
|
|
900
|
+
import json
|
|
901
|
+
import datetime
|
|
902
|
+
import re
|
|
903
|
+
|
|
904
|
+
data = _input.first()["json"]
|
|
905
|
+
processed = json.loads(data.get("json_string", "{}"))
|
|
906
|
+
|
|
907
|
+
return [{"json": processed}]
|
|
908
|
+
```
|
|
909
|
+
|
|
910
|
+
### 2. Fall Back to n8n Nodes
|
|
911
|
+
|
|
912
|
+
```python
|
|
913
|
+
# For operations requiring external libraries,
|
|
914
|
+
# use n8n nodes instead:
|
|
915
|
+
# - HTTP Request for API calls
|
|
916
|
+
# - Postgres/MySQL for databases
|
|
917
|
+
# - Extract from File for parsing
|
|
918
|
+
|
|
919
|
+
# Then process results in Code node
|
|
920
|
+
result = _input.first()["json"]
|
|
921
|
+
return [{"json": {"processed": result}}]
|
|
922
|
+
```
|
|
923
|
+
|
|
924
|
+
### 3. Combine Multiple Modules
|
|
925
|
+
|
|
926
|
+
```python
|
|
927
|
+
import json
|
|
928
|
+
import base64
|
|
929
|
+
import hashlib
|
|
930
|
+
from datetime import datetime
|
|
931
|
+
|
|
932
|
+
# Combine modules for complex operations
|
|
933
|
+
data = _input.first()["json"]["body"]
|
|
934
|
+
|
|
935
|
+
# Hash sensitive data
|
|
936
|
+
user_id = hashlib.sha256(data.get("email", "").encode()).hexdigest()[:16]
|
|
937
|
+
|
|
938
|
+
# Encode for storage
|
|
939
|
+
encoded_data = base64.b64encode(json.dumps(data).encode()).decode()
|
|
940
|
+
|
|
941
|
+
return [{
|
|
942
|
+
"json": {
|
|
943
|
+
"user_id": user_id,
|
|
944
|
+
"encoded_data": encoded_data,
|
|
945
|
+
"timestamp": datetime.now().isoformat()
|
|
946
|
+
}
|
|
947
|
+
}]
|
|
948
|
+
```
|
|
949
|
+
|
|
950
|
+
---
|
|
951
|
+
|
|
952
|
+
## Summary
|
|
953
|
+
|
|
954
|
+
**Most Useful Modules**:
|
|
955
|
+
1. json - Parse/generate JSON
|
|
956
|
+
2. datetime - Date operations
|
|
957
|
+
3. re - Regular expressions
|
|
958
|
+
4. base64 - Encoding
|
|
959
|
+
5. hashlib - Hashing
|
|
960
|
+
6. urllib.parse - URL operations
|
|
961
|
+
|
|
962
|
+
**Critical Limitation**:
|
|
963
|
+
- NO external libraries (requests, pandas, numpy, etc.)
|
|
964
|
+
|
|
965
|
+
**Recommended Approach**:
|
|
966
|
+
- Use **JavaScript** for 95% of use cases
|
|
967
|
+
- Use Python only when specifically needed
|
|
968
|
+
- Use n8n nodes for operations requiring external libraries
|
|
969
|
+
|
|
970
|
+
**See Also**:
|
|
971
|
+
- [SKILL.md](SKILL.md) - Python Code overview
|
|
972
|
+
- [DATA_ACCESS.md](DATA_ACCESS.md) - Data access patterns
|
|
973
|
+
- [COMMON_PATTERNS.md](COMMON_PATTERNS.md) - Production patterns
|
|
974
|
+
- [ERROR_PATTERNS.md](ERROR_PATTERNS.md) - Avoid common mistakes
|