@superglue/cli 1.1.6 → 1.1.8
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/.claude-plugin/plugin.json +2 -9
- package/dist/cli.js +201 -25
- package/dist/skills/superglue/SKILL.md +53 -14
- package/dist/skills/superglue/references/redis.md +190 -0
- package/package.json +2 -1
- package/skills/superglue/SKILL.md +53 -14
- package/skills/superglue/references/redis.md +190 -0
- package/dist/dist/cli.js +0 -23731
- package/dist/dist/skills/superglue/SKILL.md +0 -628
- package/dist/dist/skills/superglue/agents/openai.yaml +0 -7
- package/dist/dist/skills/superglue/assets/superglue.png +0 -0
- package/dist/dist/skills/superglue/references/databases.md +0 -88
- package/dist/dist/skills/superglue/references/file-servers.md +0 -136
- package/dist/dist/skills/superglue/references/integration.md +0 -279
- package/dist/dist/skills/superglue/references/transforms-and-output.md +0 -92
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# Redis Steps
|
|
2
|
+
|
|
3
|
+
## Step Configuration
|
|
4
|
+
|
|
5
|
+
```typescript
|
|
6
|
+
{
|
|
7
|
+
type: "request",
|
|
8
|
+
systemId: "my_redis",
|
|
9
|
+
url: "redis://<<my_redis_username>>:<<my_redis_password>>@<<my_redis_host>>:<<my_redis_port>>/<<my_redis_database>>",
|
|
10
|
+
method: "POST", // ignored for Redis but required by schema
|
|
11
|
+
body: '{"command": "GET", "args": ["<<keyName>>"]}'
|
|
12
|
+
}
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Configure the connection URL depending on which credentials are saved in the stored Redis system - reference them accordingly.
|
|
16
|
+
|
|
17
|
+
## URL Format
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
redis://user:password@host:port/database
|
|
21
|
+
rediss://user:password@host:port/database (TLS)
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
- `redis://` for standard connections
|
|
25
|
+
- `rediss://` for TLS-encrypted connections (e.g. Redis Cloud, AWS ElastiCache with encryption)
|
|
26
|
+
- `/database` is the database number (0-15), defaults to 0 if omitted
|
|
27
|
+
|
|
28
|
+
All credential variables are resolved before connecting. Trailing slashes are cleaned.
|
|
29
|
+
|
|
30
|
+
## Body Format
|
|
31
|
+
|
|
32
|
+
JSON string with `command` (required) and optional `args` array. Body can be a single command object or an array of commands (pipelined in a single round-trip):
|
|
33
|
+
|
|
34
|
+
```json
|
|
35
|
+
{ "command": "GET", "args": ["mykey"] }
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Multiple commands:
|
|
39
|
+
|
|
40
|
+
```json
|
|
41
|
+
[
|
|
42
|
+
{ "command": "GET", "args": ["user:1:name"] },
|
|
43
|
+
{ "command": "HGETALL", "args": ["user:1"] }
|
|
44
|
+
]
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Common Commands
|
|
48
|
+
|
|
49
|
+
**String operations:**
|
|
50
|
+
|
|
51
|
+
```json
|
|
52
|
+
{ "command": "GET", "args": ["user:123:name"] }
|
|
53
|
+
{ "command": "SET", "args": ["user:123:name", "Alice"] }
|
|
54
|
+
{ "command": "MGET", "args": ["key1", "key2", "key3"] }
|
|
55
|
+
{ "command": "INCR", "args": ["counter"] }
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Hash operations:**
|
|
59
|
+
|
|
60
|
+
```json
|
|
61
|
+
{ "command": "HGETALL", "args": ["user:123"] }
|
|
62
|
+
{ "command": "HGET", "args": ["user:123", "email"] }
|
|
63
|
+
{ "command": "HSET", "args": ["user:123", "email", "alice@example.com"] }
|
|
64
|
+
{ "command": "HMGET", "args": ["user:123", "name", "email"] }
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**List operations:**
|
|
68
|
+
|
|
69
|
+
```json
|
|
70
|
+
{ "command": "LRANGE", "args": ["queue:tasks", "0", "-1"] }
|
|
71
|
+
{ "command": "LPUSH", "args": ["queue:tasks", "task1"] }
|
|
72
|
+
{ "command": "RPOP", "args": ["queue:tasks"] }
|
|
73
|
+
{ "command": "LLEN", "args": ["queue:tasks"] }
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**Set operations:**
|
|
77
|
+
|
|
78
|
+
```json
|
|
79
|
+
{ "command": "SMEMBERS", "args": ["tags:post:1"] }
|
|
80
|
+
{ "command": "SADD", "args": ["tags:post:1", "redis", "database"] }
|
|
81
|
+
{ "command": "SISMEMBER", "args": ["tags:post:1", "redis"] }
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Sorted set operations:**
|
|
85
|
+
|
|
86
|
+
```json
|
|
87
|
+
{ "command": "ZRANGE", "args": ["leaderboard", "0", "-1", "WITHSCORES"] }
|
|
88
|
+
{ "command": "ZADD", "args": ["leaderboard", "100", "player1"] }
|
|
89
|
+
{ "command": "ZRANK", "args": ["leaderboard", "player1"] }
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
**Key operations:**
|
|
93
|
+
|
|
94
|
+
```json
|
|
95
|
+
{ "command": "KEYS", "args": ["user:*"] }
|
|
96
|
+
{ "command": "EXISTS", "args": ["mykey"] }
|
|
97
|
+
{ "command": "TTL", "args": ["session:abc"] }
|
|
98
|
+
{ "command": "EXPIRE", "args": ["session:abc", "3600"] }
|
|
99
|
+
{ "command": "DEL", "args": ["mykey"] }
|
|
100
|
+
{ "command": "TYPE", "args": ["mykey"] }
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**Scan (safe iteration):**
|
|
104
|
+
|
|
105
|
+
```json
|
|
106
|
+
{ "command": "SCAN", "args": ["0", "MATCH", "user:*", "COUNT", "100"] }
|
|
107
|
+
{ "command": "HSCAN", "args": ["myhash", "0", "MATCH", "field*"] }
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Dynamic Arguments with Variables
|
|
111
|
+
|
|
112
|
+
```json
|
|
113
|
+
{ "command": "GET", "args": ["<<(sourceData) => `user:${sourceData.userId}:profile`>>"] }
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
```json
|
|
117
|
+
{ "command": "HSET", "args": ["<<userKey>>", "<<fieldName>>", "<<fieldValue>>"] }
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Connection Management
|
|
121
|
+
|
|
122
|
+
- A fresh connection is created per execution and closed after completion
|
|
123
|
+
- TLS auto-configured for `rediss://` URLs (with `rejectUnauthorized: false`)
|
|
124
|
+
- 5-second connection timeout, 30-second command timeout
|
|
125
|
+
- Array commands (pipeline) run on a single connection for efficiency
|
|
126
|
+
|
|
127
|
+
## Retry Logic
|
|
128
|
+
|
|
129
|
+
Default retries from server config. On final failure, error includes command and args.
|
|
130
|
+
|
|
131
|
+
## Return Value
|
|
132
|
+
|
|
133
|
+
Returns the raw Redis response:
|
|
134
|
+
|
|
135
|
+
- `GET` / `HGET`: string or null
|
|
136
|
+
- `HGETALL`: object with field-value pairs (flattened array from Redis, parsed by ioredis)
|
|
137
|
+
- `LRANGE` / `SMEMBERS` / `KEYS`: array of strings
|
|
138
|
+
- `SET` / `DEL` / `EXPIRE`: "OK" or integer
|
|
139
|
+
- `INCR` / `LLEN` / `SADD`: integer
|
|
140
|
+
- `MGET` / `HMGET`: array (nulls for missing keys)
|
|
141
|
+
- `SCAN` / `HSCAN`: array of [cursor, results]
|
|
142
|
+
|
|
143
|
+
## Multiple Commands (Pipeline)
|
|
144
|
+
|
|
145
|
+
Pass an array of commands to execute them in a single round-trip (like FTP/SFTP batch operations):
|
|
146
|
+
|
|
147
|
+
```json
|
|
148
|
+
[
|
|
149
|
+
{ "command": "GET", "args": ["user:1:name"] },
|
|
150
|
+
{ "command": "HGETALL", "args": ["user:1"] },
|
|
151
|
+
{ "command": "LRANGE", "args": ["tasks", "0", "-1"] }
|
|
152
|
+
]
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Returns an array of results, one per command:
|
|
156
|
+
|
|
157
|
+
```json
|
|
158
|
+
[
|
|
159
|
+
{ "command": "GET", "result": "Alice" },
|
|
160
|
+
{ "command": "HGETALL", "result": ["name", "Alice", "email", "alice@example.com"] },
|
|
161
|
+
{ "command": "LRANGE", "result": ["task3", "task2", "task1"] }
|
|
162
|
+
]
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
If an individual command fails, that entry has `error` instead of `result`:
|
|
166
|
+
|
|
167
|
+
```json
|
|
168
|
+
[
|
|
169
|
+
{ "command": "GET", "result": "Alice" },
|
|
170
|
+
{ "command": "WRONGCMD", "error": "ERR unknown command 'WRONGCMD'" }
|
|
171
|
+
]
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
A single command returns a single result. Multiple commands return an array — same pattern as FTP/SFTP operations.
|
|
175
|
+
|
|
176
|
+
## Batch Operations via Loop
|
|
177
|
+
|
|
178
|
+
Use a data selector returning an array to execute a command per item:
|
|
179
|
+
|
|
180
|
+
```javascript
|
|
181
|
+
// dataSelector: (sourceData) => sourceData.userIds
|
|
182
|
+
// body: {"command": "HGETALL", "args": ["<<(sourceData) => `user:${sourceData.currentItem}`>>"]}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Important Notes
|
|
186
|
+
|
|
187
|
+
- All args must be strings (Redis protocol is text-based) - numbers are auto-coerced
|
|
188
|
+
- Use `SCAN` instead of `KEYS` in production for large keyspaces
|
|
189
|
+
- `HGETALL` returns an empty object `{}` for non-existent keys
|
|
190
|
+
- Use array body for multi-command pipelines instead of separate steps
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@superglue/cli",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.8",
|
|
4
4
|
"bin": {
|
|
5
5
|
"sg": "./dist/cli.js"
|
|
6
6
|
},
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"fast-json-patch": "^3.1.1"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
|
+
"@superglue/shared": "file:../shared",
|
|
18
19
|
"@types/node": "^20.0.0",
|
|
19
20
|
"tsup": "^8.0.0",
|
|
20
21
|
"typescript": "^5.0.0"
|
|
@@ -235,21 +235,26 @@ sg system call --url "postgres://<<my_db_host>>:5432/mydb" \
|
|
|
235
235
|
--system-id my_db \
|
|
236
236
|
--body '{"query":"SELECT * FROM users LIMIT 5"}'
|
|
237
237
|
|
|
238
|
+
# Redis command
|
|
239
|
+
sg system call --url "redis://<<my_redis_host>>:6379/0" \
|
|
240
|
+
--system-id my_redis \
|
|
241
|
+
--body '{"command":"HGETALL","args":["user:123"]}'
|
|
242
|
+
|
|
238
243
|
# File server (SFTP)
|
|
239
244
|
sg system call --url "sftp://<<my_sftp_host>>:22/data" \
|
|
240
245
|
--system-id my_sftp \
|
|
241
246
|
--body '{"operation":"list","path":"/"}'
|
|
242
247
|
```
|
|
243
248
|
|
|
244
|
-
| Flag | Description
|
|
245
|
-
| ------------------- |
|
|
246
|
-
| `--url <url>` | Full URL with protocol (http/https/postgres/sftp/ftp/smb) |
|
|
247
|
-
| `--system-id <id>` | System ID for credential injection
|
|
248
|
-
| `--method <method>` | HTTP method (GET, POST, PUT, DELETE, PATCH)
|
|
249
|
-
| `--headers <json>` | HTTP headers JSON with credential placeholders
|
|
250
|
-
| `--body <string>` | Request body (JSON string)
|
|
251
|
-
| `--env <env>` | Environment: `dev` or `prod`
|
|
252
|
-
| `--file <key=path>` | File references (repeatable)
|
|
249
|
+
| Flag | Description |
|
|
250
|
+
| ------------------- | ---------------------------------------------------------------------- |
|
|
251
|
+
| `--url <url>` | Full URL with protocol (http/https/postgres/redis/rediss/sftp/ftp/smb) |
|
|
252
|
+
| `--system-id <id>` | System ID for credential injection |
|
|
253
|
+
| `--method <method>` | HTTP method (GET, POST, PUT, DELETE, PATCH) |
|
|
254
|
+
| `--headers <json>` | HTTP headers JSON with credential placeholders |
|
|
255
|
+
| `--body <string>` | Request body (JSON string) |
|
|
256
|
+
| `--env <env>` | Environment: `dev` or `prod` |
|
|
257
|
+
| `--file <key=path>` | File references (repeatable) |
|
|
253
258
|
|
|
254
259
|
**`sg system search-docs`** — Search system documentation.
|
|
255
260
|
|
|
@@ -366,15 +371,26 @@ All step config fields support `<<variable>>` placeholders:
|
|
|
366
371
|
| -------------------------- | --------------------------- |
|
|
367
372
|
| `<<fieldName>>` | Payload field or credential |
|
|
368
373
|
| `<<systemId_credKey>>` | System credential |
|
|
374
|
+
| `<<sg_auth_email>>` | Email of authenticated user |
|
|
369
375
|
| `<<(sourceData) => expr>>` | JavaScript expression |
|
|
370
376
|
|
|
371
377
|
**CRITICAL**: Simple `<<varName>>` only works for **top-level keys**. No dots, no nesting.
|
|
372
378
|
|
|
373
|
-
- VALID: `<<userId>>`, `<<currentItem>>`, `<<stripe_api_key>>`
|
|
379
|
+
- VALID: `<<userId>>`, `<<currentItem>>`, `<<stripe_api_key>>`, `<<sg_auth_email>>`
|
|
374
380
|
- INVALID: `<<currentItem.id>>`, `<<sourceData.userId>>` — these FAIL at runtime
|
|
375
381
|
|
|
376
382
|
For nested access, use arrow functions: `<<(sourceData) => sourceData.currentItem.id>>`
|
|
377
383
|
|
|
384
|
+
### Context Variables
|
|
385
|
+
|
|
386
|
+
Context variables provide information about the execution environment:
|
|
387
|
+
|
|
388
|
+
- `<<sg_auth_email>>` — Email of the authenticated user who triggered the tool
|
|
389
|
+
|
|
390
|
+
**Use case**: Personalize tool outputs based on who runs the tool (e.g., user-specific permissions, account lookups, audit logging).
|
|
391
|
+
|
|
392
|
+
**Important**: `sg_auth_email` is NOT available in scheduled executions. Tools using `<<sg_auth_email>>` will fail if run via scheduler.
|
|
393
|
+
|
|
378
394
|
### sourceData Object
|
|
379
395
|
|
|
380
396
|
`sourceData` is the cumulative state available to all JS expressions (data selectors, transforms, variable expressions):
|
|
@@ -442,7 +458,7 @@ Empty arrays are valid — the step simply skips execution.
|
|
|
442
458
|
|
|
443
459
|
### Two Step Types
|
|
444
460
|
|
|
445
|
-
**Request step** (HTTP, Postgres, FTP/SFTP/SMB) — makes an API call:
|
|
461
|
+
**Request step** (HTTP, Postgres, Redis, FTP/SFTP/SMB) — makes an API call:
|
|
446
462
|
|
|
447
463
|
```json
|
|
448
464
|
{
|
|
@@ -534,9 +550,31 @@ Templates auto-populate endpoints and OAuth config. Use `sg system find` to disc
|
|
|
534
550
|
|
|
535
551
|
### OAuth Flow
|
|
536
552
|
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
553
|
+
**IMPORTANT:** For OAuth systems, always use `--template` when creating the system. Templates auto-configure OAuth URLs, token exchange settings, and scopes. Without a template, OAuth will likely fail or require manual credential setup.
|
|
554
|
+
|
|
555
|
+
If you don't know the template ID, the CLI auto-detects it from the URL — but using `--template` explicitly is more reliable.
|
|
556
|
+
|
|
557
|
+
**Step 1: Create the system with template and credentials**
|
|
558
|
+
|
|
559
|
+
```bash
|
|
560
|
+
# Best: explicit template (auto-fills URL and OAuth config)
|
|
561
|
+
sg system create --name "Gmail" --template gmail \
|
|
562
|
+
--credentials '{"client_id":"...","client_secret":"..."}'
|
|
563
|
+
|
|
564
|
+
# Also works: URL-based auto-detection (template inferred from googleapis.com)
|
|
565
|
+
sg system create --name "Gmail" --url https://gmail.googleapis.com \
|
|
566
|
+
--credentials '{"client_id":"...","client_secret":"..."}'
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
**Step 2: Authenticate via OAuth**
|
|
570
|
+
|
|
571
|
+
```bash
|
|
572
|
+
sg system oauth --system-id gmail --scopes "https://www.googleapis.com/auth/gmail.readonly"
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
**Step 3:** User authenticates in browser → tokens saved automatically
|
|
576
|
+
|
|
577
|
+
**Common OAuth templates:** gmail, google_drive, google_calendar, google_sheets, slack, salesforce, github, jira, confluence, notion, airtable, hubspot, shopify, dropbox, zoom, microsoft_365
|
|
540
578
|
|
|
541
579
|
### System IDs
|
|
542
580
|
|
|
@@ -608,6 +646,7 @@ For detailed documentation on specific topics, read these files in the `referenc
|
|
|
608
646
|
| ------------------------------------- | ------------------------------------------------------------------------------------------------ |
|
|
609
647
|
| `references/integration.md` | **READ THIS** when deploying tools to production - SDK usage, REST API, webhooks, error handling |
|
|
610
648
|
| `references/databases.md` | Building tools that query PostgreSQL/MySQL databases |
|
|
649
|
+
| `references/redis.md` | Building tools that interact with Redis (commands, pipelines, data types) |
|
|
611
650
|
| `references/file-servers.md` | Building tools that interact with FTP/SFTP/SMB file servers |
|
|
612
651
|
| `references/transforms-and-output.md` | Complex data transformations, output shaping, JS sandbox constraints |
|
|
613
652
|
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# Redis Steps
|
|
2
|
+
|
|
3
|
+
## Step Configuration
|
|
4
|
+
|
|
5
|
+
```typescript
|
|
6
|
+
{
|
|
7
|
+
type: "request",
|
|
8
|
+
systemId: "my_redis",
|
|
9
|
+
url: "redis://<<my_redis_username>>:<<my_redis_password>>@<<my_redis_host>>:<<my_redis_port>>/<<my_redis_database>>",
|
|
10
|
+
method: "POST", // ignored for Redis but required by schema
|
|
11
|
+
body: '{"command": "GET", "args": ["<<keyName>>"]}'
|
|
12
|
+
}
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Configure the connection URL depending on which credentials are saved in the stored Redis system - reference them accordingly.
|
|
16
|
+
|
|
17
|
+
## URL Format
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
redis://user:password@host:port/database
|
|
21
|
+
rediss://user:password@host:port/database (TLS)
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
- `redis://` for standard connections
|
|
25
|
+
- `rediss://` for TLS-encrypted connections (e.g. Redis Cloud, AWS ElastiCache with encryption)
|
|
26
|
+
- `/database` is the database number (0-15), defaults to 0 if omitted
|
|
27
|
+
|
|
28
|
+
All credential variables are resolved before connecting. Trailing slashes are cleaned.
|
|
29
|
+
|
|
30
|
+
## Body Format
|
|
31
|
+
|
|
32
|
+
JSON string with `command` (required) and optional `args` array. Body can be a single command object or an array of commands (pipelined in a single round-trip):
|
|
33
|
+
|
|
34
|
+
```json
|
|
35
|
+
{ "command": "GET", "args": ["mykey"] }
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Multiple commands:
|
|
39
|
+
|
|
40
|
+
```json
|
|
41
|
+
[
|
|
42
|
+
{ "command": "GET", "args": ["user:1:name"] },
|
|
43
|
+
{ "command": "HGETALL", "args": ["user:1"] }
|
|
44
|
+
]
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Common Commands
|
|
48
|
+
|
|
49
|
+
**String operations:**
|
|
50
|
+
|
|
51
|
+
```json
|
|
52
|
+
{ "command": "GET", "args": ["user:123:name"] }
|
|
53
|
+
{ "command": "SET", "args": ["user:123:name", "Alice"] }
|
|
54
|
+
{ "command": "MGET", "args": ["key1", "key2", "key3"] }
|
|
55
|
+
{ "command": "INCR", "args": ["counter"] }
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Hash operations:**
|
|
59
|
+
|
|
60
|
+
```json
|
|
61
|
+
{ "command": "HGETALL", "args": ["user:123"] }
|
|
62
|
+
{ "command": "HGET", "args": ["user:123", "email"] }
|
|
63
|
+
{ "command": "HSET", "args": ["user:123", "email", "alice@example.com"] }
|
|
64
|
+
{ "command": "HMGET", "args": ["user:123", "name", "email"] }
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**List operations:**
|
|
68
|
+
|
|
69
|
+
```json
|
|
70
|
+
{ "command": "LRANGE", "args": ["queue:tasks", "0", "-1"] }
|
|
71
|
+
{ "command": "LPUSH", "args": ["queue:tasks", "task1"] }
|
|
72
|
+
{ "command": "RPOP", "args": ["queue:tasks"] }
|
|
73
|
+
{ "command": "LLEN", "args": ["queue:tasks"] }
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**Set operations:**
|
|
77
|
+
|
|
78
|
+
```json
|
|
79
|
+
{ "command": "SMEMBERS", "args": ["tags:post:1"] }
|
|
80
|
+
{ "command": "SADD", "args": ["tags:post:1", "redis", "database"] }
|
|
81
|
+
{ "command": "SISMEMBER", "args": ["tags:post:1", "redis"] }
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Sorted set operations:**
|
|
85
|
+
|
|
86
|
+
```json
|
|
87
|
+
{ "command": "ZRANGE", "args": ["leaderboard", "0", "-1", "WITHSCORES"] }
|
|
88
|
+
{ "command": "ZADD", "args": ["leaderboard", "100", "player1"] }
|
|
89
|
+
{ "command": "ZRANK", "args": ["leaderboard", "player1"] }
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
**Key operations:**
|
|
93
|
+
|
|
94
|
+
```json
|
|
95
|
+
{ "command": "KEYS", "args": ["user:*"] }
|
|
96
|
+
{ "command": "EXISTS", "args": ["mykey"] }
|
|
97
|
+
{ "command": "TTL", "args": ["session:abc"] }
|
|
98
|
+
{ "command": "EXPIRE", "args": ["session:abc", "3600"] }
|
|
99
|
+
{ "command": "DEL", "args": ["mykey"] }
|
|
100
|
+
{ "command": "TYPE", "args": ["mykey"] }
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**Scan (safe iteration):**
|
|
104
|
+
|
|
105
|
+
```json
|
|
106
|
+
{ "command": "SCAN", "args": ["0", "MATCH", "user:*", "COUNT", "100"] }
|
|
107
|
+
{ "command": "HSCAN", "args": ["myhash", "0", "MATCH", "field*"] }
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Dynamic Arguments with Variables
|
|
111
|
+
|
|
112
|
+
```json
|
|
113
|
+
{ "command": "GET", "args": ["<<(sourceData) => `user:${sourceData.userId}:profile`>>"] }
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
```json
|
|
117
|
+
{ "command": "HSET", "args": ["<<userKey>>", "<<fieldName>>", "<<fieldValue>>"] }
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Connection Management
|
|
121
|
+
|
|
122
|
+
- A fresh connection is created per execution and closed after completion
|
|
123
|
+
- TLS auto-configured for `rediss://` URLs (with `rejectUnauthorized: false`)
|
|
124
|
+
- 5-second connection timeout, 30-second command timeout
|
|
125
|
+
- Array commands (pipeline) run on a single connection for efficiency
|
|
126
|
+
|
|
127
|
+
## Retry Logic
|
|
128
|
+
|
|
129
|
+
Default retries from server config. On final failure, error includes command and args.
|
|
130
|
+
|
|
131
|
+
## Return Value
|
|
132
|
+
|
|
133
|
+
Returns the raw Redis response:
|
|
134
|
+
|
|
135
|
+
- `GET` / `HGET`: string or null
|
|
136
|
+
- `HGETALL`: object with field-value pairs (flattened array from Redis, parsed by ioredis)
|
|
137
|
+
- `LRANGE` / `SMEMBERS` / `KEYS`: array of strings
|
|
138
|
+
- `SET` / `DEL` / `EXPIRE`: "OK" or integer
|
|
139
|
+
- `INCR` / `LLEN` / `SADD`: integer
|
|
140
|
+
- `MGET` / `HMGET`: array (nulls for missing keys)
|
|
141
|
+
- `SCAN` / `HSCAN`: array of [cursor, results]
|
|
142
|
+
|
|
143
|
+
## Multiple Commands (Pipeline)
|
|
144
|
+
|
|
145
|
+
Pass an array of commands to execute them in a single round-trip (like FTP/SFTP batch operations):
|
|
146
|
+
|
|
147
|
+
```json
|
|
148
|
+
[
|
|
149
|
+
{ "command": "GET", "args": ["user:1:name"] },
|
|
150
|
+
{ "command": "HGETALL", "args": ["user:1"] },
|
|
151
|
+
{ "command": "LRANGE", "args": ["tasks", "0", "-1"] }
|
|
152
|
+
]
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Returns an array of results, one per command:
|
|
156
|
+
|
|
157
|
+
```json
|
|
158
|
+
[
|
|
159
|
+
{ "command": "GET", "result": "Alice" },
|
|
160
|
+
{ "command": "HGETALL", "result": ["name", "Alice", "email", "alice@example.com"] },
|
|
161
|
+
{ "command": "LRANGE", "result": ["task3", "task2", "task1"] }
|
|
162
|
+
]
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
If an individual command fails, that entry has `error` instead of `result`:
|
|
166
|
+
|
|
167
|
+
```json
|
|
168
|
+
[
|
|
169
|
+
{ "command": "GET", "result": "Alice" },
|
|
170
|
+
{ "command": "WRONGCMD", "error": "ERR unknown command 'WRONGCMD'" }
|
|
171
|
+
]
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
A single command returns a single result. Multiple commands return an array — same pattern as FTP/SFTP operations.
|
|
175
|
+
|
|
176
|
+
## Batch Operations via Loop
|
|
177
|
+
|
|
178
|
+
Use a data selector returning an array to execute a command per item:
|
|
179
|
+
|
|
180
|
+
```javascript
|
|
181
|
+
// dataSelector: (sourceData) => sourceData.userIds
|
|
182
|
+
// body: {"command": "HGETALL", "args": ["<<(sourceData) => `user:${sourceData.currentItem}`>>"]}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Important Notes
|
|
186
|
+
|
|
187
|
+
- All args must be strings (Redis protocol is text-based) - numbers are auto-coerced
|
|
188
|
+
- Use `SCAN` instead of `KEYS` in production for large keyspaces
|
|
189
|
+
- `HGETALL` returns an empty object `{}` for non-existent keys
|
|
190
|
+
- Use array body for multi-command pipelines instead of separate steps
|