@kumiai/hub-server 0.8.0 → 0.10.0
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/lib/handlers.js +32 -9
- package/lib/memoryStore.js +11 -10
- package/package.json +8 -8
package/lib/handlers.js
CHANGED
|
@@ -286,7 +286,9 @@ export function createHandlers(params) {
|
|
|
286
286
|
// retry returns `deduped`, and the block below is gated on `!deduped`.
|
|
287
287
|
let subscribers;
|
|
288
288
|
try {
|
|
289
|
-
subscribers = await store.getSubscribers(
|
|
289
|
+
subscribers = await store.getSubscribers({
|
|
290
|
+
topicID
|
|
291
|
+
});
|
|
290
292
|
} catch (error) {
|
|
291
293
|
storeErrorReporter({
|
|
292
294
|
method: 'getSubscribers',
|
|
@@ -419,7 +421,10 @@ export function createHandlers(params) {
|
|
|
419
421
|
});
|
|
420
422
|
}
|
|
421
423
|
try {
|
|
422
|
-
await store.unsubscribe(
|
|
424
|
+
await store.unsubscribe({
|
|
425
|
+
subscriberDID: clientDID,
|
|
426
|
+
topicID
|
|
427
|
+
});
|
|
423
428
|
} catch (error) {
|
|
424
429
|
rethrowAsHandlerError(error);
|
|
425
430
|
}
|
|
@@ -684,9 +689,16 @@ export function createHandlers(params) {
|
|
|
684
689
|
// The last-resort path has no cap to cross: the slot is one entry, replaced in place.
|
|
685
690
|
try {
|
|
686
691
|
if (lastResortPackage != null) {
|
|
687
|
-
await store.storeLastResortKeyPackage(
|
|
692
|
+
await store.storeLastResortKeyPackage({
|
|
693
|
+
ownerDID: clientDID,
|
|
694
|
+
keyPackage: lastResortPackage
|
|
695
|
+
});
|
|
688
696
|
} else {
|
|
689
|
-
await Promise.all(keyPackages.map((kp)=>store.storeKeyPackage(
|
|
697
|
+
await Promise.all(keyPackages.map((kp)=>store.storeKeyPackage({
|
|
698
|
+
ownerDID: clientDID,
|
|
699
|
+
keyPackage: kp,
|
|
700
|
+
notAfter
|
|
701
|
+
})));
|
|
690
702
|
}
|
|
691
703
|
} catch (error) {
|
|
692
704
|
rethrowAsHandlerError(error);
|
|
@@ -745,7 +757,9 @@ export function createHandlers(params) {
|
|
|
745
757
|
let lastResort = null;
|
|
746
758
|
let readFailure;
|
|
747
759
|
try {
|
|
748
|
-
lastResort = await store.fetchLastResortKeyPackage(
|
|
760
|
+
lastResort = await store.fetchLastResortKeyPackage({
|
|
761
|
+
ownerDID: targetDID
|
|
762
|
+
});
|
|
749
763
|
} catch (error) {
|
|
750
764
|
readFailure = error;
|
|
751
765
|
}
|
|
@@ -778,7 +792,10 @@ export function createHandlers(params) {
|
|
|
778
792
|
// the request when nothing has been consumed and there is therefore nothing to lose.
|
|
779
793
|
let consumed;
|
|
780
794
|
try {
|
|
781
|
-
consumed = await store.fetchKeyPackages(
|
|
795
|
+
consumed = await store.fetchKeyPackages({
|
|
796
|
+
ownerDID: targetDID,
|
|
797
|
+
count: cappedCount
|
|
798
|
+
});
|
|
782
799
|
} catch (error) {
|
|
783
800
|
rethrowAsHandlerError(error);
|
|
784
801
|
}
|
|
@@ -787,7 +804,9 @@ export function createHandlers(params) {
|
|
|
787
804
|
};
|
|
788
805
|
let lastResort = null;
|
|
789
806
|
try {
|
|
790
|
-
lastResort = await store.fetchLastResortKeyPackage(
|
|
807
|
+
lastResort = await store.fetchLastResortKeyPackage({
|
|
808
|
+
ownerDID: targetDID
|
|
809
|
+
});
|
|
791
810
|
} catch (error) {
|
|
792
811
|
// Nothing consumed, so nothing is lost by surfacing it. Otherwise the top-up was a bonus
|
|
793
812
|
// the caller never paid for: hand back what the store has already given up.
|
|
@@ -834,8 +853,12 @@ export function createHandlers(params) {
|
|
|
834
853
|
// Two independent reads for one owner: concurrent, since neither informs the other.
|
|
835
854
|
;
|
|
836
855
|
[count, stored] = await Promise.all([
|
|
837
|
-
store.countKeyPackages(
|
|
838
|
-
|
|
856
|
+
store.countKeyPackages({
|
|
857
|
+
ownerDID: clientDID
|
|
858
|
+
}),
|
|
859
|
+
store.fetchLastResortKeyPackage({
|
|
860
|
+
ownerDID: clientDID
|
|
861
|
+
})
|
|
839
862
|
]);
|
|
840
863
|
} catch (error) {
|
|
841
864
|
rethrowAsHandlerError(error);
|
package/lib/memoryStore.js
CHANGED
|
@@ -241,7 +241,8 @@ function isLive(entry, nowSeconds) {
|
|
|
241
241
|
startIndex = 0;
|
|
242
242
|
} else {
|
|
243
243
|
for(let index = 0; index < pending.length; index++){
|
|
244
|
-
|
|
244
|
+
const sequenceID = pending[index];
|
|
245
|
+
if (sequenceID !== undefined && sequenceID > params.after) {
|
|
245
246
|
startIndex = index;
|
|
246
247
|
break;
|
|
247
248
|
}
|
|
@@ -258,7 +259,7 @@ function isLive(entry, nowSeconds) {
|
|
|
258
259
|
resultMessages.push(asStoredMessage(entry));
|
|
259
260
|
}
|
|
260
261
|
}
|
|
261
|
-
const cursor = resultMessages.
|
|
262
|
+
const cursor = resultMessages.at(-1)?.sequenceID ?? null;
|
|
262
263
|
const result = {
|
|
263
264
|
messages: resultMessages,
|
|
264
265
|
cursor
|
|
@@ -294,7 +295,7 @@ function isLive(entry, nowSeconds) {
|
|
|
294
295
|
return {
|
|
295
296
|
messages,
|
|
296
297
|
head: heads.get(params.topicID) ?? null,
|
|
297
|
-
oldest: log
|
|
298
|
+
oldest: log[0] ?? null
|
|
298
299
|
};
|
|
299
300
|
},
|
|
300
301
|
async trim (params) {
|
|
@@ -360,7 +361,7 @@ function isLive(entry, nowSeconds) {
|
|
|
360
361
|
}
|
|
361
362
|
ownTopics.add(params.topicID);
|
|
362
363
|
},
|
|
363
|
-
async unsubscribe (subscriberDID, topicID) {
|
|
364
|
+
async unsubscribe ({ subscriberDID, topicID }) {
|
|
364
365
|
const subscribers = subscriptions.get(topicID);
|
|
365
366
|
if (subscribers != null) {
|
|
366
367
|
subscribers.delete(subscriberDID);
|
|
@@ -386,13 +387,13 @@ function isLive(entry, nowSeconds) {
|
|
|
386
387
|
}
|
|
387
388
|
}
|
|
388
389
|
},
|
|
389
|
-
async getSubscribers (topicID) {
|
|
390
|
+
async getSubscribers ({ topicID }) {
|
|
390
391
|
const subscribers = subscriptions.get(topicID);
|
|
391
392
|
return subscribers == null ? [] : [
|
|
392
393
|
...subscribers.keys()
|
|
393
394
|
];
|
|
394
395
|
},
|
|
395
|
-
async storeKeyPackage (ownerDID, keyPackage, notAfter) {
|
|
396
|
+
async storeKeyPackage ({ ownerDID, keyPackage, notAfter }) {
|
|
396
397
|
let packages = keyPackages.get(ownerDID);
|
|
397
398
|
if (packages == null) {
|
|
398
399
|
packages = [];
|
|
@@ -417,7 +418,7 @@ function isLive(entry, nowSeconds) {
|
|
|
417
418
|
} : {}
|
|
418
419
|
});
|
|
419
420
|
},
|
|
420
|
-
async fetchKeyPackages (ownerDID, count) {
|
|
421
|
+
async fetchKeyPackages ({ ownerDID, count }) {
|
|
421
422
|
const packages = keyPackages.get(ownerDID);
|
|
422
423
|
if (packages == null || packages.length === 0) return [];
|
|
423
424
|
const nowSeconds = Math.floor(Date.now() / 1000);
|
|
@@ -432,16 +433,16 @@ function isLive(entry, nowSeconds) {
|
|
|
432
433
|
}
|
|
433
434
|
return served;
|
|
434
435
|
},
|
|
435
|
-
async countKeyPackages (ownerDID) {
|
|
436
|
+
async countKeyPackages ({ ownerDID }) {
|
|
436
437
|
const packages = keyPackages.get(ownerDID);
|
|
437
438
|
if (packages == null) return 0;
|
|
438
439
|
const nowSeconds = Math.floor(Date.now() / 1000);
|
|
439
440
|
return packages.filter((entry)=>isLive(entry, nowSeconds)).length;
|
|
440
441
|
},
|
|
441
|
-
async storeLastResortKeyPackage (ownerDID, keyPackage) {
|
|
442
|
+
async storeLastResortKeyPackage ({ ownerDID, keyPackage }) {
|
|
442
443
|
lastResortKeyPackages.set(ownerDID, keyPackage);
|
|
443
444
|
},
|
|
444
|
-
async fetchLastResortKeyPackage (ownerDID) {
|
|
445
|
+
async fetchLastResortKeyPackage ({ ownerDID }) {
|
|
445
446
|
// No splice, ever. Reuse is the point here — this package is marked last-resort in MLS, so
|
|
446
447
|
// serving it again is by design rather than the init-key reuse `fetchKeyPackages` avoids.
|
|
447
448
|
return lastResortKeyPackages.get(ownerDID) ?? null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kumiai/hub-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Hub server for Enkaku E2EE group message routing",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"hub",
|
|
@@ -25,19 +25,19 @@
|
|
|
25
25
|
"lib/*"
|
|
26
26
|
],
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@enkaku/protocol": "^0.21.
|
|
28
|
+
"@enkaku/protocol": "^0.21.1",
|
|
29
29
|
"@enkaku/server": "^0.21.2",
|
|
30
30
|
"@kokuin/token": "^0.5.0",
|
|
31
|
-
"@kumiai/hub-protocol": "^0.
|
|
31
|
+
"@kumiai/hub-protocol": "^0.10.0",
|
|
32
32
|
"@sozai/codec": "^0.4.0",
|
|
33
33
|
"@sozai/event": "^0.1.3",
|
|
34
34
|
"@sozai/log": "^0.3.1"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"@enkaku/client": "^0.21.
|
|
37
|
+
"@enkaku/client": "^0.21.2",
|
|
38
38
|
"@enkaku/transport": "^0.21.0",
|
|
39
|
-
"@kumiai/hub-conformance": "^0.
|
|
40
|
-
"@kumiai/hub-wake": "^0.
|
|
39
|
+
"@kumiai/hub-conformance": "^0.10.0",
|
|
40
|
+
"@kumiai/hub-wake": "^0.10.0"
|
|
41
41
|
},
|
|
42
42
|
"publishConfig": {
|
|
43
43
|
"access": "public"
|
|
@@ -45,8 +45,8 @@
|
|
|
45
45
|
"scripts": {
|
|
46
46
|
"build": "pnpm run build:clean && pnpm run build:js && pnpm run build:types",
|
|
47
47
|
"build:clean": "del lib",
|
|
48
|
-
"build:js": "swc src -d ./lib --config-file ../../node_modules/@kigu/dev/swc.json --strip-leading-paths",
|
|
49
|
-
"build:types": "tsc --emitDeclarationOnly --skipLibCheck",
|
|
48
|
+
"build:js": "del 'lib/**/*.js' && swc src -d ./lib --config-file ../../node_modules/@kigu/dev/swc.json --strip-leading-paths",
|
|
49
|
+
"build:types": "del 'lib/**/*.d.ts' 'lib/**/*.d.ts.map' && tsc --emitDeclarationOnly --skipLibCheck",
|
|
50
50
|
"test": "pnpm run test:types && pnpm run test:unit",
|
|
51
51
|
"test:types": "tsc --noEmit --skipLibCheck -p tsconfig.test.json",
|
|
52
52
|
"test:unit": "vitest run"
|