@kumiai/hub-server 0.12.2 → 0.13.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 +13 -3
- package/lib/hub.d.ts +2 -2
- package/lib/hub.js +1 -0
- package/lib/index.d.ts +1 -1
- package/lib/registry.d.ts +11 -2
- package/lib/registry.js +2 -2
- package/lib/wake.js +9 -6
- package/package.json +11 -10
package/lib/handlers.js
CHANGED
|
@@ -624,7 +624,10 @@ export function createHandlers(params) {
|
|
|
624
624
|
logUnackedFrames();
|
|
625
625
|
tornDown = true;
|
|
626
626
|
notifyWindow();
|
|
627
|
-
if (receiveToken != null) registry.releaseReceiveWriter(
|
|
627
|
+
if (receiveToken != null) registry.releaseReceiveWriter({
|
|
628
|
+
did: clientDID,
|
|
629
|
+
token: receiveToken
|
|
630
|
+
});
|
|
628
631
|
registry.unregisterIfIdle(clientDID);
|
|
629
632
|
reader.cancel().catch(()=>{});
|
|
630
633
|
writer.abort(new Error('receive channel torn down')).catch(()=>{});
|
|
@@ -718,7 +721,11 @@ export function createHandlers(params) {
|
|
|
718
721
|
// Binding evicts whatever held the lane: a reconnect means the old connection broke and the
|
|
719
722
|
// server learns last, so the stale writer must give way to the live one. See
|
|
720
723
|
// `HubClientRegistry.bindReceiveWriter`.
|
|
721
|
-
const { token, evicted } = registry.bindReceiveWriter(
|
|
724
|
+
const { token, evicted } = registry.bindReceiveWriter({
|
|
725
|
+
did: clientDID,
|
|
726
|
+
writer: onLive,
|
|
727
|
+
endReceive: ()=>endEvicted?.()
|
|
728
|
+
});
|
|
722
729
|
receiveToken = token;
|
|
723
730
|
// After the bind, so the lane is never unheld between the two.
|
|
724
731
|
evicted?.();
|
|
@@ -770,7 +777,10 @@ export function createHandlers(params) {
|
|
|
770
777
|
if (!tornDown) logUnackedFrames();
|
|
771
778
|
tornDown = true;
|
|
772
779
|
notifyWindow();
|
|
773
|
-
if (receiveToken != null) registry.releaseReceiveWriter(
|
|
780
|
+
if (receiveToken != null) registry.releaseReceiveWriter({
|
|
781
|
+
did: clientDID,
|
|
782
|
+
token: receiveToken
|
|
783
|
+
});
|
|
774
784
|
registry.unregisterIfIdle(clientDID);
|
|
775
785
|
reader.cancel().catch(()=>{});
|
|
776
786
|
writer.abort(error).catch(()=>{});
|
package/lib/hub.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ServerTransportOf } from '@enkaku/protocol';
|
|
2
2
|
import type { AccessRules, ReplayOptions, ResourceLimits, Server } from '@enkaku/server';
|
|
3
3
|
import type { VerifyTokenHook } from '@kokuin/capability';
|
|
4
|
-
import type { Identity } from '@kokuin/token';
|
|
4
|
+
import type { CryptoOptions, Identity } from '@kokuin/token';
|
|
5
5
|
import type { HubProtocol, HubStore, WakeRegistry, WakeSender } from '@kumiai/hub-protocol';
|
|
6
6
|
import { type AuthorizeHook, type HubRateLimits, type HubStoreErrorHook, type KeyPackageFetchLimits } from './handlers.js';
|
|
7
7
|
import { HubClientRegistry } from './registry.js';
|
|
@@ -28,7 +28,7 @@ export type HubPurgeOptions = {
|
|
|
28
28
|
};
|
|
29
29
|
/** Replay settings a host may tune. The hub always enables replay checks and rejects stale tokens. */
|
|
30
30
|
export type HubReplayOptions = Omit<ReplayOptions, 'enabled' | 'rejectStale'>;
|
|
31
|
-
export type CreateHubParams = {
|
|
31
|
+
export type CreateHubParams = CryptoOptions & {
|
|
32
32
|
transport: ServerTransportOf<HubProtocol>;
|
|
33
33
|
store: HubStore;
|
|
34
34
|
/**
|
package/lib/hub.js
CHANGED
|
@@ -55,6 +55,7 @@ export function createHub(params) {
|
|
|
55
55
|
protocol: hubProtocol,
|
|
56
56
|
transport: params.transport,
|
|
57
57
|
identity: params.identity,
|
|
58
|
+
crypto: params.crypto,
|
|
58
59
|
accessRules: params.accessRules ?? DEFAULT_HUB_ACCESS_RULES,
|
|
59
60
|
verifyToken: params.verifyToken,
|
|
60
61
|
replay: {
|
package/lib/index.d.ts
CHANGED
|
@@ -4,6 +4,6 @@ export type { CreateHubParams, HubInstance, HubPurgeOptions, HubReplayOptions }
|
|
|
4
4
|
export { createHub, DEFAULT_HUB_ACCESS_RULES } from './hub.js';
|
|
5
5
|
export { createMemoryStore, type MemoryStoreOptions } from './memoryStore.js';
|
|
6
6
|
export { createRateLimiter, type RateLimitConfig, type RateLimiter } from './rateLimit.js';
|
|
7
|
-
export type { ClientEntry } from './registry.js';
|
|
7
|
+
export type { ClientEntry, HubClientRegistryBindReceiveWriterParams, HubClientRegistryReleaseReceiveWriterParams, } from './registry.js';
|
|
8
8
|
export { HubClientRegistry } from './registry.js';
|
|
9
9
|
export { createWakeDispatcher, type WakeDispatcher, type WakeDispatcherParams, type WakeNotifyParams, } from './wake.js';
|
package/lib/registry.d.ts
CHANGED
|
@@ -7,6 +7,15 @@ export type ClientEntry = {
|
|
|
7
7
|
/** Identifies the binding, so a channel can only ever release its OWN. */
|
|
8
8
|
token: symbol | null;
|
|
9
9
|
};
|
|
10
|
+
export type HubClientRegistryBindReceiveWriterParams = {
|
|
11
|
+
did: string;
|
|
12
|
+
writer: (message: StoredMessage) => void;
|
|
13
|
+
endReceive: () => void;
|
|
14
|
+
};
|
|
15
|
+
export type HubClientRegistryReleaseReceiveWriterParams = {
|
|
16
|
+
did: string;
|
|
17
|
+
token: symbol;
|
|
18
|
+
};
|
|
10
19
|
/**
|
|
11
20
|
* Tracks online clients and their live receive-channel writers. Subscription
|
|
12
21
|
* state is durable in the store, not here — the registry only routes live
|
|
@@ -39,12 +48,12 @@ export declare class HubClientRegistry {
|
|
|
39
48
|
* it. So a release names the binding it is releasing, and one that is no longer current is a
|
|
40
49
|
* no-op.
|
|
41
50
|
*/
|
|
42
|
-
bindReceiveWriter(did
|
|
51
|
+
bindReceiveWriter({ did, writer, endReceive }: HubClientRegistryBindReceiveWriterParams): {
|
|
43
52
|
token: symbol;
|
|
44
53
|
evicted: (() => void) | null;
|
|
45
54
|
};
|
|
46
55
|
/** Clear the binding this token names. A token that is no longer current is a no-op. */
|
|
47
|
-
releaseReceiveWriter(did
|
|
56
|
+
releaseReceiveWriter({ did, token }: HubClientRegistryReleaseReceiveWriterParams): void;
|
|
48
57
|
getClient(did: string): ClientEntry | undefined;
|
|
49
58
|
isOnline(did: string): boolean;
|
|
50
59
|
isWriterBound(did: string): boolean;
|
package/lib/registry.js
CHANGED
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
* null the writer the new channel has just bound, leaving the DID online with nothing behind
|
|
48
48
|
* it. So a release names the binding it is releasing, and one that is no longer current is a
|
|
49
49
|
* no-op.
|
|
50
|
-
*/ bindReceiveWriter(did, writer, endReceive) {
|
|
50
|
+
*/ bindReceiveWriter({ did, writer, endReceive }) {
|
|
51
51
|
const entry = this.#clients.get(did);
|
|
52
52
|
if (entry == null) return {
|
|
53
53
|
token: Symbol('unbound'),
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
evicted
|
|
64
64
|
};
|
|
65
65
|
}
|
|
66
|
-
/** Clear the binding this token names. A token that is no longer current is a no-op. */ releaseReceiveWriter(did, token) {
|
|
66
|
+
/** Clear the binding this token names. A token that is no longer current is a no-op. */ releaseReceiveWriter({ did, token }) {
|
|
67
67
|
const entry = this.#clients.get(did);
|
|
68
68
|
if (entry == null || entry.token !== token) return;
|
|
69
69
|
entry.sendMessage = null;
|
package/lib/wake.js
CHANGED
|
@@ -31,12 +31,15 @@ const DEFAULT_DEBOUNCE_MS = 10_000;
|
|
|
31
31
|
const registration = await params.registry.get(did);
|
|
32
32
|
if (registration == null) return;
|
|
33
33
|
const body = sealWakeHint({
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
hint: {
|
|
35
|
+
topicID,
|
|
36
|
+
sequenceID,
|
|
37
|
+
count
|
|
38
|
+
},
|
|
39
|
+
recipient: {
|
|
40
|
+
publicKey: fromB64U(registration.publicKey),
|
|
41
|
+
authSecret: fromB64U(registration.authSecret)
|
|
42
|
+
}
|
|
40
43
|
});
|
|
41
44
|
const verdict = await params.sender.send({
|
|
42
45
|
registration,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kumiai/hub-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Hub server for Enkaku E2EE group message routing",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"hub",
|
|
@@ -25,20 +25,21 @@
|
|
|
25
25
|
"lib/*"
|
|
26
26
|
],
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@enkaku/protocol": "^0.
|
|
29
|
-
"@enkaku/server": "^0.
|
|
30
|
-
"@kokuin/capability": "^0.
|
|
31
|
-
"@kokuin/token": "^0.
|
|
32
|
-
"@kumiai/hub-protocol": "^0.
|
|
28
|
+
"@enkaku/protocol": "^0.23.0",
|
|
29
|
+
"@enkaku/server": "^0.23.0",
|
|
30
|
+
"@kokuin/capability": "^0.7.0",
|
|
31
|
+
"@kokuin/token": "^0.7.0",
|
|
32
|
+
"@kumiai/hub-protocol": "^0.13.0",
|
|
33
33
|
"@sozai/codec": "^0.4.4",
|
|
34
34
|
"@sozai/event": "^0.1.6",
|
|
35
35
|
"@sozai/log": "^0.4.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@enkaku/client": "^0.
|
|
39
|
-
"@enkaku/transport": "^0.
|
|
40
|
-
"@
|
|
41
|
-
"@kumiai/hub-
|
|
38
|
+
"@enkaku/client": "^0.23.0",
|
|
39
|
+
"@enkaku/transport": "^0.23.0",
|
|
40
|
+
"@kokuin/crypto": "^0.7.0",
|
|
41
|
+
"@kumiai/hub-conformance": "^0.13.0",
|
|
42
|
+
"@kumiai/hub-wake": "^0.13.0"
|
|
42
43
|
},
|
|
43
44
|
"publishConfig": {
|
|
44
45
|
"access": "public"
|