@radishbot/sdk 0.7.2 → 0.8.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/dist/cli.js +696 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +37 -105
- package/package.json +3 -3
- package/src/cli.ts +1 -1
- package/src/connection.ts +2 -78
- package/src/index.ts +55 -78
- package/src/module_bindings/add_log_reducer.ts +1 -1
- package/src/module_bindings/add_logs_batch_reducer.ts +1 -1
- package/src/module_bindings/create_sub_flow_reducer.ts +1 -1
- package/src/module_bindings/finish_flow_reducer.ts +1 -1
- package/src/module_bindings/start_action_reducer.ts +1 -1
package/dist/index.js
CHANGED
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
} from "spacetimedb";
|
|
19
19
|
var add_log_reducer_default = {
|
|
20
20
|
keyHash: __t.string(),
|
|
21
|
-
|
|
21
|
+
exportToken: __t.string(),
|
|
22
22
|
level: __t.string(),
|
|
23
23
|
message: __t.string(),
|
|
24
24
|
data: __t.string()
|
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
} from "spacetimedb";
|
|
31
31
|
var add_logs_batch_reducer_default = {
|
|
32
32
|
keyHash: __t2.string(),
|
|
33
|
-
|
|
33
|
+
exportToken: __t2.string(),
|
|
34
34
|
entries: __t2.string()
|
|
35
35
|
};
|
|
36
36
|
|
|
@@ -52,7 +52,7 @@ import {
|
|
|
52
52
|
} from "spacetimedb";
|
|
53
53
|
var create_sub_flow_reducer_default = {
|
|
54
54
|
keyHash: __t4.string(),
|
|
55
|
-
|
|
55
|
+
parentExportToken: __t4.string(),
|
|
56
56
|
name: __t4.string(),
|
|
57
57
|
timeoutSeconds: __t4.u64(),
|
|
58
58
|
exportToken: __t4.string()
|
|
@@ -74,7 +74,7 @@ import {
|
|
|
74
74
|
} from "spacetimedb";
|
|
75
75
|
var finish_flow_reducer_default = {
|
|
76
76
|
keyHash: __t6.string(),
|
|
77
|
-
|
|
77
|
+
exportToken: __t6.string(),
|
|
78
78
|
status: __t6.string(),
|
|
79
79
|
errorMessage: __t6.string()
|
|
80
80
|
};
|
|
@@ -95,7 +95,7 @@ import {
|
|
|
95
95
|
} from "spacetimedb";
|
|
96
96
|
var start_action_reducer_default = {
|
|
97
97
|
keyHash: __t8.string(),
|
|
98
|
-
|
|
98
|
+
exportToken: __t8.string(),
|
|
99
99
|
name: __t8.string()
|
|
100
100
|
};
|
|
101
101
|
|
|
@@ -283,15 +283,10 @@ class SdkConnection {
|
|
|
283
283
|
_dbName;
|
|
284
284
|
_conn = null;
|
|
285
285
|
_connectPromise = null;
|
|
286
|
-
_keyHash = null;
|
|
287
|
-
_flowWaiters = new Map;
|
|
288
286
|
constructor(host, dbName) {
|
|
289
287
|
this._host = host;
|
|
290
288
|
this._dbName = dbName;
|
|
291
289
|
}
|
|
292
|
-
setKeyHash(keyHash) {
|
|
293
|
-
this._keyHash = keyHash;
|
|
294
|
-
}
|
|
295
290
|
async connect() {
|
|
296
291
|
if (this._conn)
|
|
297
292
|
return this._conn;
|
|
@@ -300,14 +295,7 @@ class SdkConnection {
|
|
|
300
295
|
this._connectPromise = new Promise((resolve, reject) => {
|
|
301
296
|
DbConnection.builder().withUri(this._host).withDatabaseName(this._dbName).onConnect((c, _identity, _token) => {
|
|
302
297
|
this._conn = c;
|
|
303
|
-
c
|
|
304
|
-
const waiter = this._flowWaiters.get(row.exportToken);
|
|
305
|
-
if (waiter) {
|
|
306
|
-
this._flowWaiters.delete(row.exportToken);
|
|
307
|
-
waiter(row.id);
|
|
308
|
-
}
|
|
309
|
-
});
|
|
310
|
-
c.subscriptionBuilder().onApplied(() => resolve(c)).subscribe([`SELECT * FROM flow WHERE key_hash = '${this._keyHash}'`]);
|
|
298
|
+
resolve(c);
|
|
311
299
|
}).onConnectError((_ctx, err) => {
|
|
312
300
|
reject(new Error(`SpacetimeDB connection failed: ${err}`));
|
|
313
301
|
}).build();
|
|
@@ -319,47 +307,6 @@ class SdkConnection {
|
|
|
319
307
|
throw new Error("Not connected");
|
|
320
308
|
return this._conn;
|
|
321
309
|
}
|
|
322
|
-
async createFlowAndResolveId(reducerCall, exportToken) {
|
|
323
|
-
const conn = this.conn;
|
|
324
|
-
for (const f of conn.db.flow.iter()) {
|
|
325
|
-
if (f.exportToken === exportToken)
|
|
326
|
-
return f.id;
|
|
327
|
-
}
|
|
328
|
-
return new Promise((resolve, reject) => {
|
|
329
|
-
let resolved = false;
|
|
330
|
-
this._flowWaiters.set(exportToken, (id) => {
|
|
331
|
-
if (!resolved) {
|
|
332
|
-
resolved = true;
|
|
333
|
-
clearInterval(interval);
|
|
334
|
-
resolve(id);
|
|
335
|
-
}
|
|
336
|
-
});
|
|
337
|
-
reducerCall();
|
|
338
|
-
const interval = setInterval(() => {
|
|
339
|
-
if (resolved) {
|
|
340
|
-
clearInterval(interval);
|
|
341
|
-
return;
|
|
342
|
-
}
|
|
343
|
-
for (const f of conn.db.flow.iter()) {
|
|
344
|
-
if (f.exportToken === exportToken) {
|
|
345
|
-
resolved = true;
|
|
346
|
-
clearInterval(interval);
|
|
347
|
-
this._flowWaiters.delete(exportToken);
|
|
348
|
-
resolve(f.id);
|
|
349
|
-
return;
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
}, 100);
|
|
353
|
-
setTimeout(() => {
|
|
354
|
-
if (!resolved) {
|
|
355
|
-
resolved = true;
|
|
356
|
-
clearInterval(interval);
|
|
357
|
-
this._flowWaiters.delete(exportToken);
|
|
358
|
-
reject(new Error(`Flow creation timed out for token ${exportToken}`));
|
|
359
|
-
}
|
|
360
|
-
}, 15000);
|
|
361
|
-
});
|
|
362
|
-
}
|
|
363
310
|
disconnect() {
|
|
364
311
|
if (this._conn) {
|
|
365
312
|
this._conn.disconnect();
|
|
@@ -441,7 +388,6 @@ function generateToken() {
|
|
|
441
388
|
class Flow {
|
|
442
389
|
_sdk;
|
|
443
390
|
_keyHash;
|
|
444
|
-
_id = null;
|
|
445
391
|
_exportToken;
|
|
446
392
|
_ready;
|
|
447
393
|
_resolveReady;
|
|
@@ -449,15 +395,15 @@ class Flow {
|
|
|
449
395
|
_flushScheduled = false;
|
|
450
396
|
_isReady = false;
|
|
451
397
|
_finished = false;
|
|
452
|
-
|
|
398
|
+
_parentExportToken;
|
|
453
399
|
_name;
|
|
454
400
|
_timeoutSeconds;
|
|
455
401
|
_release;
|
|
456
402
|
_runId;
|
|
457
|
-
constructor(sdk, keyHash,
|
|
403
|
+
constructor(sdk, keyHash, parentExportToken, name, timeoutSeconds, release = "", runId = "") {
|
|
458
404
|
this._sdk = sdk;
|
|
459
405
|
this._keyHash = keyHash;
|
|
460
|
-
this.
|
|
406
|
+
this._parentExportToken = parentExportToken;
|
|
461
407
|
this._name = name;
|
|
462
408
|
this._timeoutSeconds = !timeoutSeconds || timeoutSeconds === Infinity ? 0n : BigInt(timeoutSeconds);
|
|
463
409
|
this._release = release;
|
|
@@ -467,31 +413,24 @@ class Flow {
|
|
|
467
413
|
this._resolveReady = resolve;
|
|
468
414
|
});
|
|
469
415
|
}
|
|
470
|
-
|
|
416
|
+
_create() {
|
|
471
417
|
const conn = this._sdk.conn;
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
if (this._parentId === 0n) {
|
|
476
|
-
const id = await this._sdk.createFlowAndResolveId(() => conn.reducers.createRootFlow({
|
|
477
|
-
keyHash,
|
|
418
|
+
if (this._parentExportToken === null) {
|
|
419
|
+
conn.reducers.createRootFlow({
|
|
420
|
+
keyHash: this._keyHash,
|
|
478
421
|
runId: this._runId,
|
|
479
|
-
timeoutSeconds,
|
|
480
|
-
exportToken,
|
|
422
|
+
timeoutSeconds: this._timeoutSeconds,
|
|
423
|
+
exportToken: this._exportToken,
|
|
481
424
|
release: this._release
|
|
482
|
-
})
|
|
483
|
-
this._id = id;
|
|
425
|
+
});
|
|
484
426
|
} else {
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
exportToken
|
|
493
|
-
}), exportToken);
|
|
494
|
-
this._id = id;
|
|
427
|
+
conn.reducers.createSubFlow({
|
|
428
|
+
keyHash: this._keyHash,
|
|
429
|
+
parentExportToken: this._parentExportToken,
|
|
430
|
+
name: this._name,
|
|
431
|
+
timeoutSeconds: this._timeoutSeconds,
|
|
432
|
+
exportToken: this._exportToken
|
|
433
|
+
});
|
|
495
434
|
}
|
|
496
435
|
this._isReady = true;
|
|
497
436
|
this._resolveReady();
|
|
@@ -500,7 +439,7 @@ class Flow {
|
|
|
500
439
|
static MAX_PENDING = 1e4;
|
|
501
440
|
log(message, data, level = "info") {
|
|
502
441
|
if (this._finished) {
|
|
503
|
-
|
|
442
|
+
_origConsole.warn(`[radish] Cannot log to finished flow`);
|
|
504
443
|
return this;
|
|
505
444
|
}
|
|
506
445
|
if (this._pendingLogs.length >= Flow.MAX_PENDING) {
|
|
@@ -528,9 +467,8 @@ class Flow {
|
|
|
528
467
|
return this.log(message, data, "debug");
|
|
529
468
|
}
|
|
530
469
|
action(name, timeoutSeconds = 100) {
|
|
531
|
-
const child = new Flow(this._sdk, this._keyHash,
|
|
470
|
+
const child = new Flow(this._sdk, this._keyHash, this._exportToken, name, timeoutSeconds, this._release, this._runId);
|
|
532
471
|
this._ready.then(() => {
|
|
533
|
-
child._parentId = this._id;
|
|
534
472
|
child._create();
|
|
535
473
|
});
|
|
536
474
|
return child;
|
|
@@ -561,7 +499,7 @@ class Flow {
|
|
|
561
499
|
this._finished = true;
|
|
562
500
|
this._sdk.conn.reducers.finishFlow({
|
|
563
501
|
keyHash: this._keyHash,
|
|
564
|
-
|
|
502
|
+
exportToken: this._exportToken,
|
|
565
503
|
status: "finished",
|
|
566
504
|
errorMessage: ""
|
|
567
505
|
});
|
|
@@ -576,7 +514,7 @@ class Flow {
|
|
|
576
514
|
this._finished = true;
|
|
577
515
|
this._sdk.conn.reducers.finishFlow({
|
|
578
516
|
keyHash: this._keyHash,
|
|
579
|
-
|
|
517
|
+
exportToken: this._exportToken,
|
|
580
518
|
status: "error",
|
|
581
519
|
errorMessage
|
|
582
520
|
});
|
|
@@ -584,19 +522,16 @@ class Flow {
|
|
|
584
522
|
get runId() {
|
|
585
523
|
return this._runId;
|
|
586
524
|
}
|
|
587
|
-
|
|
588
|
-
|
|
525
|
+
get token() {
|
|
526
|
+
return this._exportToken;
|
|
527
|
+
}
|
|
528
|
+
exportID() {
|
|
589
529
|
return JSON.stringify({
|
|
590
|
-
flowId: this._id.toString(),
|
|
591
530
|
exportToken: this._exportToken,
|
|
592
531
|
keyHash: this._keyHash,
|
|
593
532
|
runId: this._runId
|
|
594
533
|
});
|
|
595
534
|
}
|
|
596
|
-
async getId() {
|
|
597
|
-
await this._ready;
|
|
598
|
-
return this._id;
|
|
599
|
-
}
|
|
600
535
|
disconnect() {
|
|
601
536
|
this._sdk.disconnect();
|
|
602
537
|
}
|
|
@@ -623,7 +558,7 @@ class Flow {
|
|
|
623
558
|
const e = batch[0];
|
|
624
559
|
conn.reducers.addLog({
|
|
625
560
|
keyHash: this._keyHash,
|
|
626
|
-
|
|
561
|
+
exportToken: this._exportToken,
|
|
627
562
|
level: e.level,
|
|
628
563
|
message: e.message,
|
|
629
564
|
data: e.data
|
|
@@ -631,7 +566,7 @@ class Flow {
|
|
|
631
566
|
} else {
|
|
632
567
|
conn.reducers.addLogsBatch({
|
|
633
568
|
keyHash: this._keyHash,
|
|
634
|
-
|
|
569
|
+
exportToken: this._exportToken,
|
|
635
570
|
entries: JSON.stringify(batch)
|
|
636
571
|
});
|
|
637
572
|
}
|
|
@@ -656,16 +591,13 @@ async function RL(secretKey, options = {}) {
|
|
|
656
591
|
const retentionDays = parseRetention(retention);
|
|
657
592
|
const keyHash = await hashKey(secretKey);
|
|
658
593
|
const sdk = new SdkConnection(host, dbName);
|
|
659
|
-
sdk.setKeyHash(keyHash);
|
|
660
594
|
try {
|
|
661
595
|
await sdk.connect();
|
|
662
596
|
} catch (e) {
|
|
663
597
|
throw new Error(`Failed to connect to Radish (${host}/${dbName}): ${e instanceof Error ? e.message : e}`);
|
|
664
598
|
}
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
} catch {}
|
|
668
|
-
const root = new Flow(sdk, keyHash, 0n, "/", 0, release, runId);
|
|
599
|
+
sdk.conn.reducers.registerKey({ keyHash, label, retentionDays: BigInt(retentionDays) });
|
|
600
|
+
const root = new Flow(sdk, keyHash, null, "/", 0, release, runId);
|
|
669
601
|
root._create();
|
|
670
602
|
return root;
|
|
671
603
|
}
|
|
@@ -678,9 +610,9 @@ async function restoreFlow(secretKey, exportedId, options = {}) {
|
|
|
678
610
|
}
|
|
679
611
|
const sdk = new SdkConnection(host, dbName);
|
|
680
612
|
await sdk.connect();
|
|
681
|
-
const flow = new Flow(sdk, keyHash,
|
|
682
|
-
flow._id = BigInt(parsed.flowId);
|
|
613
|
+
const flow = new Flow(sdk, keyHash, null, "restored", 100, "", parsed.runId || "");
|
|
683
614
|
flow._exportToken = parsed.exportToken;
|
|
615
|
+
flow._isReady = true;
|
|
684
616
|
flow._resolveReady();
|
|
685
617
|
return flow;
|
|
686
618
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@radishbot/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
14
|
"bin": {
|
|
15
|
-
"radish": "./
|
|
15
|
+
"radish": "./dist/cli.js"
|
|
16
16
|
},
|
|
17
17
|
"files": [
|
|
18
18
|
"src",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"README.md"
|
|
21
21
|
],
|
|
22
22
|
"scripts": {
|
|
23
|
-
"build": "bun build ./src/index.ts --outdir dist --target node --format esm --external spacetimedb --external ws",
|
|
23
|
+
"build": "bun build ./src/index.ts --outdir dist --target node --format esm --external spacetimedb --external ws && bun build ./src/cli.ts --outfile dist/cli.js --target node --format esm --external spacetimedb --external ws",
|
|
24
24
|
"prepublishOnly": "bun run build",
|
|
25
25
|
"cli": "bun run ./src/cli.ts"
|
|
26
26
|
},
|
package/src/cli.ts
CHANGED
package/src/connection.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* SpacetimeDB connection wrapper for the Radish SDK.
|
|
3
|
-
*
|
|
3
|
+
* No subscription needed — all operations use exportToken (fire-and-forget reducers).
|
|
4
4
|
*/
|
|
5
5
|
import { DbConnection as StdbConnection } from "./module_bindings";
|
|
6
6
|
|
|
@@ -9,20 +9,12 @@ export class SdkConnection {
|
|
|
9
9
|
private _dbName: string;
|
|
10
10
|
private _conn: StdbConnection | null = null;
|
|
11
11
|
private _connectPromise: Promise<StdbConnection> | null = null;
|
|
12
|
-
private _keyHash: string | null = null;
|
|
13
|
-
|
|
14
|
-
// Callbacks waiting for flow creation by exportToken
|
|
15
|
-
private _flowWaiters = new Map<string, (id: bigint) => void>();
|
|
16
12
|
|
|
17
13
|
constructor(host: string, dbName: string) {
|
|
18
14
|
this._host = host;
|
|
19
15
|
this._dbName = dbName;
|
|
20
16
|
}
|
|
21
17
|
|
|
22
|
-
setKeyHash(keyHash: string): void {
|
|
23
|
-
this._keyHash = keyHash;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
18
|
async connect(): Promise<StdbConnection> {
|
|
27
19
|
if (this._conn) return this._conn;
|
|
28
20
|
if (this._connectPromise) return this._connectPromise;
|
|
@@ -33,19 +25,7 @@ export class SdkConnection {
|
|
|
33
25
|
.withDatabaseName(this._dbName)
|
|
34
26
|
.onConnect((c, _identity, _token) => {
|
|
35
27
|
this._conn = c;
|
|
36
|
-
|
|
37
|
-
// Resolve flow waiters immediately when new flows arrive
|
|
38
|
-
c.db.flow.onInsert((_ctx, row) => {
|
|
39
|
-
const waiter = this._flowWaiters.get(row.exportToken);
|
|
40
|
-
if (waiter) {
|
|
41
|
-
this._flowWaiters.delete(row.exportToken);
|
|
42
|
-
waiter(row.id);
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
c.subscriptionBuilder()
|
|
47
|
-
.onApplied(() => resolve(c))
|
|
48
|
-
.subscribe([`SELECT * FROM flow WHERE key_hash = '${this._keyHash}'`]);
|
|
28
|
+
resolve(c);
|
|
49
29
|
})
|
|
50
30
|
.onConnectError((_ctx, err) => {
|
|
51
31
|
reject(new Error(`SpacetimeDB connection failed: ${err}`));
|
|
@@ -61,62 +41,6 @@ export class SdkConnection {
|
|
|
61
41
|
return this._conn;
|
|
62
42
|
}
|
|
63
43
|
|
|
64
|
-
/**
|
|
65
|
-
* Call a reducer and wait for the flow to appear in the subscription.
|
|
66
|
-
* Returns the server-assigned flow ID.
|
|
67
|
-
*/
|
|
68
|
-
async createFlowAndResolveId(reducerCall: () => void, exportToken: string): Promise<bigint> {
|
|
69
|
-
const conn = this.conn;
|
|
70
|
-
|
|
71
|
-
// Check if flow already exists (from a previous subscription update)
|
|
72
|
-
for (const f of conn.db.flow.iter()) {
|
|
73
|
-
if (f.exportToken === exportToken) return f.id;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
return new Promise<bigint>((resolve, reject) => {
|
|
77
|
-
let resolved = false;
|
|
78
|
-
|
|
79
|
-
// Register waiter — triggered by onInsert handler in connect()
|
|
80
|
-
this._flowWaiters.set(exportToken, (id) => {
|
|
81
|
-
if (!resolved) {
|
|
82
|
-
resolved = true;
|
|
83
|
-
clearInterval(interval);
|
|
84
|
-
resolve(id);
|
|
85
|
-
}
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
// Call the reducer
|
|
89
|
-
reducerCall();
|
|
90
|
-
|
|
91
|
-
// Poll as fallback in case onInsert fires before waiter is registered
|
|
92
|
-
const interval = setInterval(() => {
|
|
93
|
-
if (resolved) {
|
|
94
|
-
clearInterval(interval);
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
for (const f of conn.db.flow.iter()) {
|
|
98
|
-
if (f.exportToken === exportToken) {
|
|
99
|
-
resolved = true;
|
|
100
|
-
clearInterval(interval);
|
|
101
|
-
this._flowWaiters.delete(exportToken);
|
|
102
|
-
resolve(f.id);
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}, 100);
|
|
107
|
-
|
|
108
|
-
// Timeout after 15 seconds (properly rejects the promise)
|
|
109
|
-
setTimeout(() => {
|
|
110
|
-
if (!resolved) {
|
|
111
|
-
resolved = true;
|
|
112
|
-
clearInterval(interval);
|
|
113
|
-
this._flowWaiters.delete(exportToken);
|
|
114
|
-
reject(new Error(`Flow creation timed out for token ${exportToken}`));
|
|
115
|
-
}
|
|
116
|
-
}, 15_000);
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
|
|
120
44
|
disconnect(): void {
|
|
121
45
|
if (this._conn) {
|
|
122
46
|
this._conn.disconnect();
|