@radishbot/sdk 0.2.0 → 0.2.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/README.md +96 -57
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,20 +13,20 @@ npm install @radishbot/sdk
|
|
|
13
13
|
## Quick Start
|
|
14
14
|
|
|
15
15
|
```ts
|
|
16
|
-
import { RL, generateKey } from
|
|
16
|
+
import { RL, generateKey } from "@radishbot/sdk";
|
|
17
17
|
|
|
18
18
|
const key = generateKey(); // save this — it's your dashboard login
|
|
19
19
|
|
|
20
|
-
const root = await RL(key);
|
|
20
|
+
const root = await RL(key, { release: "v1.0.0", retention: "30d" });
|
|
21
21
|
|
|
22
|
-
await root.a(
|
|
23
|
-
console.log(
|
|
22
|
+
await root.a("handle-request", async (req) => {
|
|
23
|
+
console.log("GET /api/users"); // automatically captured
|
|
24
24
|
|
|
25
|
-
const users = await req.a(
|
|
26
|
-
return await db.query(
|
|
25
|
+
const users = await req.a("db-query", async () => {
|
|
26
|
+
return await db.query("SELECT * FROM users");
|
|
27
27
|
});
|
|
28
28
|
|
|
29
|
-
console.log(
|
|
29
|
+
console.log("Done", { count: users.length });
|
|
30
30
|
});
|
|
31
31
|
|
|
32
32
|
await root.finish();
|
|
@@ -39,12 +39,12 @@ Open the dashboard, paste your key, see everything.
|
|
|
39
39
|
Inside `.a()` callbacks, `console.log/warn/error/debug` are automatically captured as action logs. Output still prints to the terminal — but it also gets sent to the dashboard with full context.
|
|
40
40
|
|
|
41
41
|
```ts
|
|
42
|
-
await root.a(
|
|
43
|
-
console.log(
|
|
44
|
-
console.warn(
|
|
45
|
-
console.error(
|
|
46
|
-
console.debug(
|
|
47
|
-
console.log(
|
|
42
|
+
await root.a("migrate", async () => {
|
|
43
|
+
console.log("Starting migration"); // → info log
|
|
44
|
+
console.warn("Deprecated column found"); // → warn log
|
|
45
|
+
console.error("Failed to migrate users"); // → error log
|
|
46
|
+
console.debug("SQL: ALTER TABLE ..."); // → debug log
|
|
47
|
+
console.log("Done", { tables: 5 }); // → info log with data
|
|
48
48
|
});
|
|
49
49
|
```
|
|
50
50
|
|
|
@@ -57,15 +57,15 @@ Actions are nested scopes. Every `RL()` call creates a root action at `/`. Sub-a
|
|
|
57
57
|
```ts
|
|
58
58
|
const root = await RL(key);
|
|
59
59
|
|
|
60
|
-
await root.a(
|
|
61
|
-
console.log(
|
|
60
|
+
await root.a("request", async (req) => {
|
|
61
|
+
console.log("handling request");
|
|
62
62
|
|
|
63
|
-
await req.a(
|
|
64
|
-
console.log(
|
|
63
|
+
await req.a("database", async () => {
|
|
64
|
+
console.log("querying users");
|
|
65
65
|
}); // auto-finished
|
|
66
66
|
|
|
67
|
-
await req.a(
|
|
68
|
-
console.log(
|
|
67
|
+
await req.a("response", async () => {
|
|
68
|
+
console.log("sending 200");
|
|
69
69
|
}); // auto-finished
|
|
70
70
|
}); // auto-finished
|
|
71
71
|
|
|
@@ -75,16 +75,16 @@ await root.finish();
|
|
|
75
75
|
If your function throws, the action is marked as errored and the exception propagates:
|
|
76
76
|
|
|
77
77
|
```ts
|
|
78
|
-
await root.a(
|
|
79
|
-
throw new Error(
|
|
78
|
+
await root.a("risky-op", async () => {
|
|
79
|
+
throw new Error("something broke");
|
|
80
80
|
}); // action → error, rethrows
|
|
81
81
|
```
|
|
82
82
|
|
|
83
83
|
Return values pass through:
|
|
84
84
|
|
|
85
85
|
```ts
|
|
86
|
-
const users = await flow.a(
|
|
87
|
-
return await db.query(
|
|
86
|
+
const users = await flow.a("db-query", async () => {
|
|
87
|
+
return await db.query("SELECT * FROM users");
|
|
88
88
|
});
|
|
89
89
|
// users is the query result
|
|
90
90
|
```
|
|
@@ -92,9 +92,9 @@ const users = await flow.a('db-query', async () => {
|
|
|
92
92
|
Duplicate names are allowed — the dashboard shows them as `request:1`, `request:2`, etc:
|
|
93
93
|
|
|
94
94
|
```ts
|
|
95
|
-
await root.a(
|
|
95
|
+
await root.a("batch", async (batch) => {
|
|
96
96
|
for (const item of items) {
|
|
97
|
-
await batch.a(
|
|
97
|
+
await batch.a("request", async () => {
|
|
98
98
|
await processItem(item);
|
|
99
99
|
});
|
|
100
100
|
}
|
|
@@ -104,10 +104,10 @@ await root.a('batch', async (batch) => {
|
|
|
104
104
|
For long-lived actions (websockets, streams), use the manual API:
|
|
105
105
|
|
|
106
106
|
```ts
|
|
107
|
-
const stream = root.action(
|
|
108
|
-
stream.info(
|
|
107
|
+
const stream = root.action("websocket");
|
|
108
|
+
stream.info("connected");
|
|
109
109
|
// ... hours later ...
|
|
110
|
-
stream.info(
|
|
110
|
+
stream.info("disconnected");
|
|
111
111
|
await stream.finish();
|
|
112
112
|
```
|
|
113
113
|
|
|
@@ -116,10 +116,10 @@ await stream.finish();
|
|
|
116
116
|
Outside of `.a()` callbacks, or when you want to log to a specific action:
|
|
117
117
|
|
|
118
118
|
```ts
|
|
119
|
-
action.info(
|
|
120
|
-
action.warn(
|
|
121
|
-
action.error(
|
|
122
|
-
action.debug(
|
|
119
|
+
action.info("request received", { method: "POST", path: "/api/users" });
|
|
120
|
+
action.warn("rate limit approaching", { remaining: 3 });
|
|
121
|
+
action.error("query failed", new Error("connection refused"));
|
|
122
|
+
action.debug("cache hit", { key: "user:123", ttl: 300 });
|
|
123
123
|
```
|
|
124
124
|
|
|
125
125
|
## Cross-Context Actions
|
|
@@ -128,35 +128,74 @@ Export an action's handle to continue logging from another process, worker, or s
|
|
|
128
128
|
|
|
129
129
|
```ts
|
|
130
130
|
// Service A
|
|
131
|
-
const action = root.action(
|
|
131
|
+
const action = root.action("job");
|
|
132
132
|
const handle = await action.exportID();
|
|
133
133
|
// pass handle to service B via queue, HTTP, etc.
|
|
134
134
|
|
|
135
135
|
// Service B
|
|
136
|
-
import { restoreFlow } from
|
|
136
|
+
import { restoreFlow } from "@radishbot/sdk";
|
|
137
137
|
const action = await restoreFlow(key, handle);
|
|
138
|
-
action.info(
|
|
138
|
+
action.info("continuing from service B");
|
|
139
139
|
await action.finish();
|
|
140
140
|
```
|
|
141
141
|
|
|
142
|
+
## Release Tracking
|
|
143
|
+
|
|
144
|
+
Tag every flow with a version or commit SHA. Errors are tracked per-release, and regressions (errors reappearing after being resolved) are detected automatically.
|
|
145
|
+
|
|
146
|
+
```ts
|
|
147
|
+
const root = await RL(key, { release: "v1.2.3" });
|
|
148
|
+
// or
|
|
149
|
+
const root = await RL(key, { release: process.env.GIT_SHA });
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Sub-flows inherit the release from the root automatically.
|
|
153
|
+
|
|
154
|
+
## Retention & Garbage Collection
|
|
155
|
+
|
|
156
|
+
Each key has a retention period. Flows older than the retention window are automatically deleted (along with their logs and actions) by a GC job that runs every 3 hours.
|
|
157
|
+
|
|
158
|
+
```ts
|
|
159
|
+
const root = await RL(key, { retention: "30d" }); // default
|
|
160
|
+
const root = await RL(key, { retention: "7d" }); // keep 1 week
|
|
161
|
+
const root = await RL(key, { retention: "90d" }); // keep 3 months
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Calling `RL()` with a new retention value updates the stored retention for that key.
|
|
165
|
+
|
|
166
|
+
## Error Grouping
|
|
167
|
+
|
|
168
|
+
Errors are automatically deduplicated by normalizing the error message (stripping numbers, UUIDs) and combining it with the flow path. This means:
|
|
169
|
+
|
|
170
|
+
- `"User 123 not found"` and `"User 456 not found"` at `/request/db-query` group together
|
|
171
|
+
- Each group tracks: count, first/last seen, latest flow, and release
|
|
172
|
+
- Resolving an error group and seeing it again marks it as **regressed**
|
|
173
|
+
- Groups can be marked as `resolved` or `ignored` from the dashboard
|
|
174
|
+
|
|
142
175
|
## Configuration
|
|
143
176
|
|
|
144
177
|
```ts
|
|
145
178
|
const root = await RL(key, {
|
|
146
|
-
host:
|
|
147
|
-
dbName:
|
|
148
|
-
defaultTimeout: 100,
|
|
179
|
+
host: "wss://maincloud.spacetimedb.com", // default
|
|
180
|
+
dbName: "radish-log", // default
|
|
181
|
+
defaultTimeout: 100, // seconds, default 100
|
|
182
|
+
release: "v1.0.0", // version or commit SHA
|
|
183
|
+
retention: "30d", // data retention period
|
|
149
184
|
});
|
|
150
185
|
```
|
|
151
186
|
|
|
152
187
|
Sub-actions can have their own timeout:
|
|
153
188
|
|
|
154
189
|
```ts
|
|
155
|
-
await root.a(
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
190
|
+
await root.a(
|
|
191
|
+
"quick-task",
|
|
192
|
+
async () => {
|
|
193
|
+
// ...
|
|
194
|
+
},
|
|
195
|
+
10,
|
|
196
|
+
); // 10 second timeout
|
|
197
|
+
|
|
198
|
+
const slow = root.action("batch-job", 3600); // 1 hour
|
|
160
199
|
```
|
|
161
200
|
|
|
162
201
|
Actions that exceed their timeout are automatically marked as timed out.
|
|
@@ -165,7 +204,7 @@ Actions that exceed their timeout are automatically marked as timed out.
|
|
|
165
204
|
|
|
166
205
|
### `RL(secretKey, options?) → Promise<Flow>`
|
|
167
206
|
|
|
168
|
-
Connect and create a root action.
|
|
207
|
+
Connect and create a root action. Options: `host`, `dbName`, `defaultTimeout`, `release`, `retention`.
|
|
169
208
|
|
|
170
209
|
### `generateKey() → string`
|
|
171
210
|
|
|
@@ -177,16 +216,16 @@ Restore an action from an exported handle string.
|
|
|
177
216
|
|
|
178
217
|
### Flow (Action)
|
|
179
218
|
|
|
180
|
-
| Method
|
|
181
|
-
|
|
182
|
-
| `.a(name, fn, timeout?)`
|
|
183
|
-
| `.action(name, timeout?)`
|
|
184
|
-
| `.finish()`
|
|
185
|
-
| `.finishWithError(err?)`
|
|
186
|
-
| `.info(msg, data?)`
|
|
187
|
-
| `.warn(msg, data?)`
|
|
188
|
-
| `.error(msg, data?)`
|
|
189
|
-
| `.debug(msg, data?)`
|
|
190
|
-
| `.log(msg, data?, level?)` | Log at any level.
|
|
191
|
-
| `.exportID()`
|
|
192
|
-
| `.getId()`
|
|
219
|
+
| Method | Description |
|
|
220
|
+
| -------------------------- | ------------------------------------------------------------------ |
|
|
221
|
+
| `.a(name, fn, timeout?)` | Run a sub-action. Auto-finish, console capture. Returns fn result. |
|
|
222
|
+
| `.action(name, timeout?)` | Create a sub-action manually. |
|
|
223
|
+
| `.finish()` | Finish the action. |
|
|
224
|
+
| `.finishWithError(err?)` | Finish the action as errored. |
|
|
225
|
+
| `.info(msg, data?)` | Log at info level. |
|
|
226
|
+
| `.warn(msg, data?)` | Log at warn level. |
|
|
227
|
+
| `.error(msg, data?)` | Log at error level. |
|
|
228
|
+
| `.debug(msg, data?)` | Log at debug level. |
|
|
229
|
+
| `.log(msg, data?, level?)` | Log at any level. |
|
|
230
|
+
| `.exportID()` | Export handle for cross-context restore. |
|
|
231
|
+
| `.getId()` | Get server-assigned action ID. |
|