@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 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(topicID);
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(clientDID, topicID);
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(clientDID, lastResortPackage);
692
+ await store.storeLastResortKeyPackage({
693
+ ownerDID: clientDID,
694
+ keyPackage: lastResortPackage
695
+ });
688
696
  } else {
689
- await Promise.all(keyPackages.map((kp)=>store.storeKeyPackage(clientDID, kp, notAfter)));
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(targetDID);
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(targetDID, cappedCount);
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(targetDID);
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(clientDID),
838
- store.fetchLastResortKeyPackage(clientDID)
856
+ store.countKeyPackages({
857
+ ownerDID: clientDID
858
+ }),
859
+ store.fetchLastResortKeyPackage({
860
+ ownerDID: clientDID
861
+ })
839
862
  ]);
840
863
  } catch (error) {
841
864
  rethrowAsHandlerError(error);
@@ -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
- if (pending[index] > params.after) {
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.length > 0 ? resultMessages[resultMessages.length - 1].sequenceID : null;
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.length > 0 ? log[0] : null
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.8.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.0",
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.8.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.1",
37
+ "@enkaku/client": "^0.21.2",
38
38
  "@enkaku/transport": "^0.21.0",
39
- "@kumiai/hub-conformance": "^0.8.0",
40
- "@kumiai/hub-wake": "^0.8.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"