@dxos/messaging 0.6.5 → 0.6.6-main.e1a6e1f
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/lib/browser/index.mjs +52 -48
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +52 -48
- package/dist/lib/node/index.cjs.map +3 -3
- package/dist/lib/node/meta.json +1 -1
- package/dist/types/src/signal-client/signal-client.d.ts +6 -9
- package/dist/types/src/signal-client/signal-client.d.ts.map +1 -1
- package/dist/types/src/signal-manager/edge-signal-manager.d.ts +39 -0
- package/dist/types/src/signal-manager/edge-signal-manager.d.ts.map +1 -0
- package/dist/types/src/signal-manager/edge-signal-manager.test.d.ts +2 -0
- package/dist/types/src/signal-manager/edge-signal-manager.test.d.ts.map +1 -0
- package/dist/types/src/signal-manager/signal-manager.d.ts +1 -8
- package/dist/types/src/signal-manager/signal-manager.d.ts.map +1 -1
- package/dist/types/src/signal-manager/websocket-signal-manager.d.ts.map +1 -1
- package/dist/types/src/signal-methods.d.ts +13 -1
- package/dist/types/src/signal-methods.d.ts.map +1 -1
- package/dist/types/src/testing.d.ts +10 -1
- package/dist/types/src/testing.d.ts.map +1 -1
- package/package.json +14 -13
- package/src/signal-client/signal-client.test.ts +13 -14
- package/src/signal-client/signal-client.ts +10 -7
- package/src/signal-manager/edge-signal-manager.test.ts +71 -0
- package/src/signal-manager/edge-signal-manager.ts +127 -0
- package/src/signal-manager/signal-manager.ts +1 -5
- package/src/signal-manager/websocket-signal-manager.test.ts +1 -15
- package/src/signal-manager/websocket-signal-manager.ts +3 -6
- package/src/signal-methods.ts +12 -1
- package/src/testing.ts +22 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signal-client.d.ts","sourceRoot":"","sources":["../../../../src/signal-client/signal-client.ts"],"names":[],"mappings":"AAIA,OAAO,EAAgB,KAAK,EAAsD,MAAM,aAAa,CAAC;AACtG,OAAO,
|
|
1
|
+
{"version":3,"file":"signal-client.d.ts","sourceRoot":"","sources":["../../../../src/signal-client/signal-client.ts"],"names":[],"mappings":"AAIA,OAAO,EAAgB,KAAK,EAAsD,MAAM,aAAa,CAAC;AACtG,OAAO,EAAmC,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE1E,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAGvC,OAAO,EAAe,KAAK,UAAU,EAAE,MAAM,wCAAwC,CAAC;AAKtF,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,mBAAmB,EAAE,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAO9F;;;;;GAKG;AAEH,qBAAa,YAAa,SAAQ,QAAS,YAAW,mBAAmB;IAsCrE,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;IAtChC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA6B;IAEtD,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,UAAU,CAAC,CAAQ;IAC3B,OAAO,CAAC,yBAAyB,CAAS;IAE1C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAiB;IAC9C,OAAO,CAAC,cAAc,CAAC,CAAU;IACjC,OAAO,CAAC,OAAO,CAAC,CAAkB;IAElC,OAAO,CAAC,cAAc,CAAC,CAAe;IACtC,OAAO,CAAC,cAAc,CAAC,CAAe;IAEtC;;OAEG;IACH,OAAO,CAAC,eAAe,CAA6B;IAEpD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA8B;IAO1D,QAAQ,CAAC,aAAa,sBAA6B;IAEnD,SAAgB,SAAS,iBAAwB;IACjD,SAAgB,UAAU;eAAsB,SAAS;oBAAc,UAAU;OAAM;IAEvF;;;;;OAKG;gBAEgB,KAAK,EAAE,MAAM,EACb,YAAY,CAAC,SAAQ,GAAG,aAAA;cAgBlB,KAAK;cA+CL,MAAM,CAAC,GAAG,EAAE,KAAK;cAWjB,MAAM;IAY/B,SAAS,IAAI,YAAY;IAUnB,IAAI,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,SAAS,CAAC;QAAC,MAAM,EAAE,SAAS,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAOlE,KAAK,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,SAAS,CAAC;QAAC,MAAM,EAAE,SAAS,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAMnE,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAQxC,iBAAiB,CAAC,MAAM,EAAE,SAAS;IAMnC,mBAAmB,CAAC,MAAM,EAAE,SAAS;IAK3C,OAAO,CAAC,4BAA4B;IAIpC,OAAO,CAAC,aAAa;YAuDP,UAAU;IAmBxB,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,eAAe;IAcvB,OAAO,CAAC,SAAS;IAOjB,OAAO,CAAC,uBAAuB;YAOjB,gBAAgB;CAQ/B"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Event } from '@dxos/async';
|
|
2
|
+
import { Resource } from '@dxos/context';
|
|
3
|
+
import { type EdgeClient } from '@dxos/edge-client';
|
|
4
|
+
import { PublicKey } from '@dxos/keys';
|
|
5
|
+
import { type SwarmEvent } from '@dxos/protocols/proto/dxos/mesh/signal';
|
|
6
|
+
import { type Message, type SignalMethods } from '../signal-methods';
|
|
7
|
+
export declare class EdgeSignal extends Resource implements SignalMethods {
|
|
8
|
+
swarmEvent: Event<{
|
|
9
|
+
topic: PublicKey;
|
|
10
|
+
swarmEvent: SwarmEvent;
|
|
11
|
+
}>;
|
|
12
|
+
onMessage: Event<Message>;
|
|
13
|
+
/**
|
|
14
|
+
* swarm key -> peers in the swarm
|
|
15
|
+
*/
|
|
16
|
+
private readonly _swarmPeers;
|
|
17
|
+
private readonly _messengerClient;
|
|
18
|
+
constructor({ messengerClient }: {
|
|
19
|
+
messengerClient: EdgeClient;
|
|
20
|
+
});
|
|
21
|
+
protected _open(): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Warning: PeerId is inferred from messengerClient
|
|
24
|
+
*/
|
|
25
|
+
join({ topic }: {
|
|
26
|
+
topic: PublicKey;
|
|
27
|
+
peerId: PublicKey;
|
|
28
|
+
}): Promise<void>;
|
|
29
|
+
leave({ topic }: {
|
|
30
|
+
topic: PublicKey;
|
|
31
|
+
peerId: PublicKey;
|
|
32
|
+
}): Promise<void>;
|
|
33
|
+
sendMessage(message: Message): Promise<void>;
|
|
34
|
+
subscribeMessages(peerId: PublicKey): Promise<void>;
|
|
35
|
+
unsubscribeMessages(peerId: PublicKey): Promise<void>;
|
|
36
|
+
private _onMessage;
|
|
37
|
+
private _processSwarmResponse;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=edge-signal-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edge-signal-manager.d.ts","sourceRoot":"","sources":["../../../../src/signal-manager/edge-signal-manager.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAY,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE9D,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAQvC,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,wCAAwC,CAAC;AAGzE,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGrE,qBAAa,UAAW,SAAQ,QAAS,YAAW,aAAa;IACxD,UAAU;eAAsB,SAAS;oBAAc,UAAU;OAAM;IACvE,SAAS,iBAAwB;IAExC;;OAEG;IAEH,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAoE;IAChG,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAa;gBAElC,EAAE,eAAe,EAAE,EAAE;QAAE,eAAe,EAAE,UAAU,CAAA;KAAE;cAKvC,KAAK;IAI9B;;OAEG;IACG,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE;QAAE,KAAK,EAAE,SAAS,CAAC;QAAC,MAAM,EAAE,SAAS,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAUvE,KAAK,CAAC,EAAE,KAAK,EAAE,EAAE;QAAE,KAAK,EAAE,SAAS,CAAC;QAAC,MAAM,EAAE,SAAS,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAUxE,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAI5C,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAInD,mBAAmB,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3D,OAAO,CAAC,UAAU;IAUlB,OAAO,CAAC,qBAAqB;CAuC9B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edge-signal-manager.test.d.ts","sourceRoot":"","sources":["../../../../src/signal-manager/edge-signal-manager.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { type Event } from '@dxos/async';
|
|
2
|
-
import { type
|
|
3
|
-
import { type SwarmEvent } from '@dxos/protocols/proto/dxos/mesh/signal';
|
|
4
|
-
import { type Message, type SignalMethods, type SignalStatus } from '../signal-methods';
|
|
2
|
+
import { type SignalMethods, type SignalStatus } from '../signal-methods';
|
|
5
3
|
/**
|
|
6
4
|
* Manages a collection of signaling clients.
|
|
7
5
|
*/
|
|
@@ -10,10 +8,5 @@ export interface SignalManager extends SignalMethods {
|
|
|
10
8
|
close(): Promise<void>;
|
|
11
9
|
getStatus(): SignalStatus[];
|
|
12
10
|
statusChanged: Event<SignalStatus[]>;
|
|
13
|
-
swarmEvent: Event<{
|
|
14
|
-
topic: PublicKey;
|
|
15
|
-
swarmEvent: SwarmEvent;
|
|
16
|
-
}>;
|
|
17
|
-
onMessage: Event<Message>;
|
|
18
11
|
}
|
|
19
12
|
//# sourceMappingURL=signal-manager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signal-manager.d.ts","sourceRoot":"","sources":["../../../../src/signal-manager/signal-manager.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"signal-manager.d.ts","sourceRoot":"","sources":["../../../../src/signal-manager/signal-manager.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAE1E;;GAEG;AACH,MAAM,WAAW,aAAc,SAAQ,aAAa;IAClD,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,SAAS,IAAI,YAAY,EAAE,CAAC;IAE5B,aAAa,EAAE,KAAK,CAAC,YAAY,EAAE,CAAC,CAAC;CACtC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"websocket-signal-manager.d.ts","sourceRoot":"","sources":["../../../../src/signal-manager/websocket-signal-manager.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,EAAuB,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,sBAAsB,CAAC;AAGhD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAGvC,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,wCAAwC,CAAC;AAGzE,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAGtD,OAAO,EAAgD,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAKpG;;GAEG;AACH,qBAAa,sBAAuB,YAAW,aAAa;IA4BxD,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;IA5BhC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA0C;IACnE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAuC;IAEhE;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAa;IAEpD,OAAO,CAAC,IAAI,CAAW;IACvB,OAAO,CAAC,OAAO,CAAS;IAExB,QAAQ,CAAC,YAAY,sBAA6B;IAClD,QAAQ,CAAC,aAAa,wBAA+B;IACrD,QAAQ,CAAC,UAAU;eACV,SAAS;oBACJ,UAAU;OACnB;IAEL,QAAQ,CAAC,SAAS;gBACR,SAAS;mBACN,SAAS;iBACX,GAAG;OACT;IAEL,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA8B;gBAGvC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,MAAM,EAAE,EACjC,YAAY,CAAC,SAAQ,GAAG,aAAA;
|
|
1
|
+
{"version":3,"file":"websocket-signal-manager.d.ts","sourceRoot":"","sources":["../../../../src/signal-manager/websocket-signal-manager.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,EAAuB,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,sBAAsB,CAAC;AAGhD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAGvC,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,wCAAwC,CAAC;AAGzE,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAGtD,OAAO,EAAgD,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAKpG;;GAEG;AACH,qBAAa,sBAAuB,YAAW,aAAa;IA4BxD,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;IA5BhC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA0C;IACnE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAuC;IAEhE;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAa;IAEpD,OAAO,CAAC,IAAI,CAAW;IACvB,OAAO,CAAC,OAAO,CAAS;IAExB,QAAQ,CAAC,YAAY,sBAA6B;IAClD,QAAQ,CAAC,aAAa,wBAA+B;IACrD,QAAQ,CAAC,UAAU;eACV,SAAS;oBACJ,UAAU;OACnB;IAEL,QAAQ,CAAC,SAAS;gBACR,SAAS;mBACN,SAAS;iBACX,GAAG;OACT;IAEL,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA8B;gBAGvC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,MAAM,EAAE,EACjC,YAAY,CAAC,SAAQ,GAAG,aAAA;IAsBrC,IAAI;IAgBJ,KAAK;IASL,aAAa,CAAC,UAAU,EAAE,MAAM;IAYtC,SAAS,IAAI,YAAY,EAAE;IAKrB,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;QAAE,KAAK,EAAE,SAAS,CAAC;QAAC,MAAM,EAAE,SAAS,CAAA;KAAE;IAO/D,KAAK,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;QAAE,KAAK,EAAE,SAAS,CAAC;QAAC,MAAM,EAAE,SAAS,CAAA;KAAE;IAMhE,WAAW,CAAC,EAChB,MAAM,EACN,SAAS,EACT,OAAO,GACR,EAAE;QACD,MAAM,EAAE,SAAS,CAAC;QAClB,SAAS,EAAE,SAAS,CAAC;QACrB,OAAO,EAAE,GAAG,CAAC;KACd,GAAG,OAAO,CAAC,IAAI,CAAC;IAwBX,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IAiB1D,OAAO,CAAC,sBAAsB;IAQxB,iBAAiB,CAAC,MAAM,EAAE,SAAS;IAOnC,mBAAmB,CAAC,MAAM,EAAE,SAAS;IAO3C,OAAO,CAAC,YAAY;YAMN,cAAc;CAO7B"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { type Event } from '@dxos/async';
|
|
1
2
|
import { type PublicKey } from '@dxos/keys';
|
|
2
|
-
import { type SignalState } from '@dxos/protocols/proto/dxos/mesh/signal';
|
|
3
|
+
import { type SwarmEvent, type SignalState } from '@dxos/protocols/proto/dxos/mesh/signal';
|
|
3
4
|
export interface Message {
|
|
4
5
|
author: PublicKey;
|
|
5
6
|
recipient: PublicKey;
|
|
@@ -20,6 +21,17 @@ export type SignalStatus = {
|
|
|
20
21
|
* Message routing interface.
|
|
21
22
|
*/
|
|
22
23
|
export interface SignalMethods {
|
|
24
|
+
/**
|
|
25
|
+
* Emits when other peers join or leave the swarm.
|
|
26
|
+
*/
|
|
27
|
+
swarmEvent: Event<{
|
|
28
|
+
topic: PublicKey;
|
|
29
|
+
swarmEvent: SwarmEvent;
|
|
30
|
+
}>;
|
|
31
|
+
/**
|
|
32
|
+
* Emits when a message is received.
|
|
33
|
+
*/
|
|
34
|
+
onMessage: Event<Message>;
|
|
23
35
|
/**
|
|
24
36
|
* Join topic on signal network, to be discoverable by other peers.
|
|
25
37
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signal-methods.d.ts","sourceRoot":"","sources":["../../../src/signal-methods.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,wCAAwC,CAAC;
|
|
1
|
+
{"version":3,"file":"signal-methods.d.ts","sourceRoot":"","sources":["../../../src/signal-methods.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,WAAW,EAAE,MAAM,wCAAwC,CAAC;AAE3F,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,SAAS,CAAC;IAClB,SAAS,EAAE,SAAS,CAAC;IACrB,OAAO,EAAE;QACP,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,UAAU,CAAC;KACnB,CAAC;CACH;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,WAAW,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,IAAI,CAAC;IACxB,eAAe,EAAE,IAAI,CAAC;CACvB,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,UAAU,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,SAAS,CAAC;QAAC,UAAU,EAAE,UAAU,CAAA;KAAE,CAAC,CAAC;IAEhE;;OAEG;IACH,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAE1B;;OAEG;IACH,IAAI,EAAE,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,SAAS,CAAC;QAAC,MAAM,EAAE,SAAS,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzE;;OAEG;IACH,KAAK,EAAE,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,SAAS,CAAC;QAAC,MAAM,EAAE,SAAS,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1E;;OAEG;IACH,WAAW,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjD;;OAEG;IAEH,iBAAiB,EAAE,CAAC,MAAM,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAExD;;OAEG;IACH,mBAAmB,EAAE,CAAC,MAAM,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3D;AAED;;GAEG;AACH,MAAM,WAAW,mBAAoB,SAAQ,aAAa;IACxD,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,SAAS,IAAI,YAAY,CAAC;CAC3B"}
|
|
@@ -3,7 +3,7 @@ import { PublicKey } from '@dxos/keys';
|
|
|
3
3
|
import { type Runtime } from '@dxos/protocols/proto/dxos/config';
|
|
4
4
|
import { Messenger } from './messenger';
|
|
5
5
|
import { type SignalManager } from './signal-manager';
|
|
6
|
-
import { type Message } from './signal-methods';
|
|
6
|
+
import { type SignalMethods, type Message } from './signal-methods';
|
|
7
7
|
export type TestBuilderOptions = {
|
|
8
8
|
signalHosts?: Runtime.Services.Signal[];
|
|
9
9
|
messageDisruption?: (msg: Message) => Message[];
|
|
@@ -28,4 +28,13 @@ export declare class TestPeer {
|
|
|
28
28
|
open(): Promise<void>;
|
|
29
29
|
close(): Promise<void>;
|
|
30
30
|
}
|
|
31
|
+
export declare const expectPeerAvailable: (client: SignalMethods, expectedTopic: PublicKey, peer: PublicKey) => Promise<{
|
|
32
|
+
topic: PublicKey;
|
|
33
|
+
swarmEvent: import("packages/core/protocols/dist/esm/src/proto/gen/dxos/mesh/signal").SwarmEvent;
|
|
34
|
+
}>;
|
|
35
|
+
export declare const expectPeerLeft: (client: SignalMethods, expectedTopic: PublicKey, peer: PublicKey) => Promise<{
|
|
36
|
+
topic: PublicKey;
|
|
37
|
+
swarmEvent: import("packages/core/protocols/dist/esm/src/proto/gen/dxos/mesh/signal").SwarmEvent;
|
|
38
|
+
}>;
|
|
39
|
+
export declare const expectReceivedMessage: (client: SignalMethods, expectedMessage: Message) => Promise<Message>;
|
|
31
40
|
//# sourceMappingURL=testing.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../../../src/testing.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,mCAAmC,CAAC;AAEjE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EACL,KAAK,aAAa,EAInB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../../../src/testing.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,mCAAmC,CAAC;AAEjE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EACL,KAAK,aAAa,EAInB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAEpE,MAAM,MAAM,kBAAkB,GAAG;IAC/B,WAAW,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;IACxC,iBAAiB,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,EAAE,CAAC;CACjD,CAAC;AAEF,qBAAa,WAAW;IAIH,OAAO,EAAE,kBAAkB;IAH9C,OAAO,CAAC,cAAc,CAAoC;IAC1D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;gBAEtB,OAAO,EAAE,kBAAkB;IAE9C,mBAAmB;IAqBnB,UAAU,IAAI,QAAQ;IAMhB,KAAK;CAGZ;AAED,qBAAa,QAAQ;IAMP,OAAO,CAAC,QAAQ,CAAC,WAAW;IALjC,MAAM,YAAsB;IAC5B,aAAa,EAAE,aAAa,CAAC;IAC7B,SAAS,EAAE,SAAS,CAAC;IACrB,eAAe,iBAAwB;gBAEjB,WAAW,EAAE,WAAW;IAKrD,eAAe,CAAC,OAAO,EAAE,OAAO;IAS1B,IAAI;IAaJ,KAAK;CAIZ;AAED,eAAO,MAAM,mBAAmB,WAAY,aAAa,iBAAiB,SAAS,QAAQ,SAAS;;;EAIjG,CAAC;AAEJ,eAAO,MAAM,cAAc,WAAY,aAAa,iBAAiB,SAAS,QAAQ,SAAS;;;EAI5F,CAAC;AAEJ,eAAO,MAAM,qBAAqB,WAAY,aAAa,mBAAmB,OAAO,qBAOpF,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/messaging",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.6-main.e1a6e1f",
|
|
4
4
|
"description": "Messaging",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -27,24 +27,25 @@
|
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"isomorphic-ws": "^5.0.0",
|
|
29
29
|
"ws": "^8.14.2",
|
|
30
|
-
"@dxos/async": "0.6.
|
|
31
|
-
"@dxos/
|
|
32
|
-
"@dxos/
|
|
33
|
-
"@dxos/
|
|
34
|
-
"@dxos/
|
|
35
|
-
"@dxos/keys": "0.6.
|
|
36
|
-
"@dxos/
|
|
37
|
-
"@dxos/
|
|
38
|
-
"@dxos/
|
|
39
|
-
"@dxos/
|
|
40
|
-
"@dxos/
|
|
30
|
+
"@dxos/async": "0.6.6-main.e1a6e1f",
|
|
31
|
+
"@dxos/context": "0.6.6-main.e1a6e1f",
|
|
32
|
+
"@dxos/edge-client": "0.6.6-main.e1a6e1f",
|
|
33
|
+
"@dxos/codec-protobuf": "0.6.6-main.e1a6e1f",
|
|
34
|
+
"@dxos/invariant": "0.6.6-main.e1a6e1f",
|
|
35
|
+
"@dxos/keys": "0.6.6-main.e1a6e1f",
|
|
36
|
+
"@dxos/log": "0.6.6-main.e1a6e1f",
|
|
37
|
+
"@dxos/rpc": "0.6.6-main.e1a6e1f",
|
|
38
|
+
"@dxos/protocols": "0.6.6-main.e1a6e1f",
|
|
39
|
+
"@dxos/node-std": "0.6.6-main.e1a6e1f",
|
|
40
|
+
"@dxos/tracing": "0.6.6-main.e1a6e1f",
|
|
41
|
+
"@dxos/util": "0.6.6-main.e1a6e1f"
|
|
41
42
|
},
|
|
42
43
|
"devDependencies": {
|
|
43
44
|
"@types/node": "^18.11.9",
|
|
44
45
|
"earljs": "~0.1.10",
|
|
45
46
|
"typescript": "^5.4.5",
|
|
46
47
|
"wait-for-expect": "^3.0.2",
|
|
47
|
-
"@dxos/signal": "0.6.
|
|
48
|
+
"@dxos/signal": "0.6.6-main.e1a6e1f"
|
|
48
49
|
},
|
|
49
50
|
"publishConfig": {
|
|
50
51
|
"access": "public"
|
|
@@ -121,20 +121,19 @@ describe('SignalClient', () => {
|
|
|
121
121
|
let nextMessage: any | null = null;
|
|
122
122
|
const nextMessageTrigger = new Trigger();
|
|
123
123
|
const id = PublicKey.random();
|
|
124
|
-
const client = new SignalClient(
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
);
|
|
124
|
+
const client = new SignalClient((options?.broker ?? broker1).url());
|
|
125
|
+
client.onMessage.on(async (msg) => {
|
|
126
|
+
nextMessage = msg;
|
|
127
|
+
nextMessageTrigger.wake();
|
|
128
|
+
});
|
|
129
|
+
client.swarmEvent.on(async ({ swarmEvent }) => {
|
|
130
|
+
if (swarmEvent.peerAvailable) {
|
|
131
|
+
peers.add(PublicKey.from(swarmEvent.peerAvailable.peer));
|
|
132
|
+
} else if (swarmEvent.peerLeft) {
|
|
133
|
+
peers.delete(PublicKey.from(swarmEvent.peerLeft.peer));
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
|
|
138
137
|
void client.open();
|
|
139
138
|
afterTest(async () => {
|
|
140
139
|
await client.close();
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { DeferredTask, Event, Trigger, scheduleTask, scheduleTaskInterval, sleep } from '@dxos/async';
|
|
6
|
-
import { type Any } from '@dxos/codec-protobuf';
|
|
7
6
|
import { type Context, cancelWithContext, Resource } from '@dxos/context';
|
|
8
7
|
import { invariant } from '@dxos/invariant';
|
|
9
8
|
import { PublicKey } from '@dxos/keys';
|
|
@@ -56,6 +55,9 @@ export class SignalClient extends Resource implements SignalClientMethods {
|
|
|
56
55
|
|
|
57
56
|
readonly statusChanged = new Event<SignalStatus>();
|
|
58
57
|
|
|
58
|
+
public readonly onMessage = new Event<Message>();
|
|
59
|
+
public readonly swarmEvent = new Event<{ topic: PublicKey; swarmEvent: SwarmEvent }>();
|
|
60
|
+
|
|
59
61
|
/**
|
|
60
62
|
* @param _host Signal server websocket URL.
|
|
61
63
|
* @param onMessage called when a new message is received.
|
|
@@ -64,8 +66,6 @@ export class SignalClient extends Resource implements SignalClientMethods {
|
|
|
64
66
|
*/
|
|
65
67
|
constructor(
|
|
66
68
|
private readonly _host: string,
|
|
67
|
-
onMessage: (params: { author: PublicKey; recipient: PublicKey; payload: Any }) => Promise<void>,
|
|
68
|
-
onSwarmEvent: (params: { topic: PublicKey; swarmEvent: SwarmEvent }) => Promise<void>,
|
|
69
69
|
private readonly _getMetadata?: () => any,
|
|
70
70
|
) {
|
|
71
71
|
super();
|
|
@@ -73,10 +73,13 @@ export class SignalClient extends Resource implements SignalClientMethods {
|
|
|
73
73
|
throw new Error(`Signal server requires a websocket URL. Provided: ${this._host}`);
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
this.localState = new SignalLocalState(
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
this.localState = new SignalLocalState(
|
|
77
|
+
async (message) => {
|
|
78
|
+
this._monitor.recordMessageReceived(message);
|
|
79
|
+
this.onMessage.emit(message);
|
|
80
|
+
},
|
|
81
|
+
async (event) => this.swarmEvent.emit(event),
|
|
82
|
+
);
|
|
80
83
|
}
|
|
81
84
|
|
|
82
85
|
protected override async _open() {
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
import { EdgeClient } from '@dxos/edge-client';
|
|
5
|
+
import { PublicKey } from '@dxos/keys';
|
|
6
|
+
import { describe, openAndClose, test } from '@dxos/test';
|
|
7
|
+
|
|
8
|
+
import { EdgeSignal } from './edge-signal-manager';
|
|
9
|
+
import { type Message } from '../signal-methods';
|
|
10
|
+
import { expectPeerAvailable, expectPeerLeft, expectReceivedMessage } from '../testing';
|
|
11
|
+
|
|
12
|
+
// TODO(mykola): Expects wrangler dev on edge repo to run. Skip to pass CI.
|
|
13
|
+
describe.skip('EdgeSignalManager', () => {
|
|
14
|
+
const setupPeer = async () => {
|
|
15
|
+
const [identityKey, deviceKey] = PublicKey.randomSequence();
|
|
16
|
+
|
|
17
|
+
const client = new EdgeClient(identityKey, deviceKey, { socketEndpoint: 'ws://localhost:8787' });
|
|
18
|
+
await openAndClose(client);
|
|
19
|
+
const edgeSignal = new EdgeSignal({ messengerClient: client });
|
|
20
|
+
await openAndClose(edgeSignal);
|
|
21
|
+
|
|
22
|
+
return { identityKey, deviceKey, client, edgeSignal };
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
test('two peers discover each other', async () => {
|
|
26
|
+
const topic = PublicKey.random();
|
|
27
|
+
const peer1 = await setupPeer();
|
|
28
|
+
const peer2 = await setupPeer();
|
|
29
|
+
|
|
30
|
+
const discover12 = expectPeerAvailable(peer1.edgeSignal, topic, peer2.deviceKey);
|
|
31
|
+
const discover21 = expectPeerAvailable(peer2.edgeSignal, topic, peer1.deviceKey);
|
|
32
|
+
|
|
33
|
+
await peer1.edgeSignal.join({ topic, peerId: peer1.deviceKey });
|
|
34
|
+
await peer2.edgeSignal.join({ topic, peerId: peer2.deviceKey });
|
|
35
|
+
|
|
36
|
+
await discover12;
|
|
37
|
+
await discover21;
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test('join and leave swarm', async () => {
|
|
41
|
+
const topic = PublicKey.random();
|
|
42
|
+
const peer1 = await setupPeer();
|
|
43
|
+
const peer2 = await setupPeer();
|
|
44
|
+
|
|
45
|
+
const discover12 = expectPeerAvailable(peer1.edgeSignal, topic, peer2.deviceKey);
|
|
46
|
+
const left12 = expectPeerLeft(peer1.edgeSignal, topic, peer2.deviceKey);
|
|
47
|
+
|
|
48
|
+
await peer1.edgeSignal.join({ topic, peerId: peer1.deviceKey });
|
|
49
|
+
await peer2.edgeSignal.join({ topic, peerId: peer2.deviceKey });
|
|
50
|
+
await discover12;
|
|
51
|
+
|
|
52
|
+
await peer2.edgeSignal.leave({ topic, peerId: peer2.deviceKey });
|
|
53
|
+
await left12;
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test('message between peers', async () => {
|
|
57
|
+
const peer1 = await setupPeer();
|
|
58
|
+
const peer2 = await setupPeer();
|
|
59
|
+
const message: Message = {
|
|
60
|
+
author: peer1.deviceKey,
|
|
61
|
+
recipient: peer2.deviceKey,
|
|
62
|
+
payload: { type_url: 'google.protobuf.Any', value: Uint8Array.from([1, 2, 3]) },
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const receivedMessage = expectReceivedMessage(peer2.edgeSignal, message);
|
|
66
|
+
await peer2.edgeSignal.subscribeMessages(peer2.deviceKey);
|
|
67
|
+
await peer1.edgeSignal.sendMessage(message);
|
|
68
|
+
|
|
69
|
+
await receivedMessage;
|
|
70
|
+
});
|
|
71
|
+
});
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { Event } from '@dxos/async';
|
|
6
|
+
import { Resource } from '@dxos/context';
|
|
7
|
+
import { protocol, type EdgeClient } from '@dxos/edge-client';
|
|
8
|
+
import { invariant } from '@dxos/invariant';
|
|
9
|
+
import { PublicKey } from '@dxos/keys';
|
|
10
|
+
import { log } from '@dxos/log';
|
|
11
|
+
import {
|
|
12
|
+
SwarmRequestSchema,
|
|
13
|
+
SwarmRequest_Action as SwarmRequestAction,
|
|
14
|
+
SwarmResponseSchema,
|
|
15
|
+
type Message as EdgeMessage,
|
|
16
|
+
} from '@dxos/protocols/buf/dxos/edge/messenger_pb';
|
|
17
|
+
import { type SwarmEvent } from '@dxos/protocols/proto/dxos/mesh/signal';
|
|
18
|
+
import { ComplexMap, ComplexSet } from '@dxos/util';
|
|
19
|
+
|
|
20
|
+
import { type Message, type SignalMethods } from '../signal-methods';
|
|
21
|
+
|
|
22
|
+
const SWARM_SERVICE_ID = 'swarm';
|
|
23
|
+
export class EdgeSignal extends Resource implements SignalMethods {
|
|
24
|
+
public swarmEvent = new Event<{ topic: PublicKey; swarmEvent: SwarmEvent }>();
|
|
25
|
+
public onMessage = new Event<Message>();
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* swarm key -> peers in the swarm
|
|
29
|
+
*/
|
|
30
|
+
// TODO(mykola): This class should not contain swarm state. Temporary before network-manager API changes to accept list of peers.
|
|
31
|
+
private readonly _swarmPeers = new ComplexMap<PublicKey, ComplexSet<PublicKey>>(PublicKey.hash);
|
|
32
|
+
private readonly _messengerClient: EdgeClient;
|
|
33
|
+
|
|
34
|
+
constructor({ messengerClient }: { messengerClient: EdgeClient }) {
|
|
35
|
+
super();
|
|
36
|
+
this._messengerClient = messengerClient;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
protected override async _open() {
|
|
40
|
+
this._ctx.onDispose(this._messengerClient.addListener((message) => this._onMessage(message)));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Warning: PeerId is inferred from messengerClient
|
|
45
|
+
*/
|
|
46
|
+
async join({ topic }: { topic: PublicKey; peerId: PublicKey }): Promise<void> {
|
|
47
|
+
this._swarmPeers.set(topic, new ComplexSet<PublicKey>(PublicKey.hash));
|
|
48
|
+
await this._messengerClient.send(
|
|
49
|
+
protocol.createMessage(SwarmRequestSchema, {
|
|
50
|
+
serviceId: SWARM_SERVICE_ID,
|
|
51
|
+
payload: { action: SwarmRequestAction.JOIN, swarmKeys: [topic.toHex()] },
|
|
52
|
+
}),
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async leave({ topic }: { topic: PublicKey; peerId: PublicKey }): Promise<void> {
|
|
57
|
+
this._swarmPeers.delete(topic);
|
|
58
|
+
await this._messengerClient.send(
|
|
59
|
+
protocol.createMessage(SwarmRequestSchema, {
|
|
60
|
+
serviceId: SWARM_SERVICE_ID,
|
|
61
|
+
payload: { action: SwarmRequestAction.LEAVE, swarmKeys: [topic.toHex()] },
|
|
62
|
+
}),
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async sendMessage(message: Message): Promise<void> {
|
|
67
|
+
throw new Error('Method not implemented.');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async subscribeMessages(peerId: PublicKey): Promise<void> {
|
|
71
|
+
throw new Error('Method not implemented.');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async unsubscribeMessages(peerId: PublicKey): Promise<void> {
|
|
75
|
+
throw new Error('Method not implemented.');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
private _onMessage(message: EdgeMessage) {
|
|
79
|
+
const type = protocol.getPayloadType(message);
|
|
80
|
+
|
|
81
|
+
switch (type) {
|
|
82
|
+
case SwarmResponseSchema.typeName: {
|
|
83
|
+
this._processSwarmResponse(message);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
private _processSwarmResponse(message: EdgeMessage) {
|
|
89
|
+
invariant(protocol.getPayloadType(message) === SwarmResponseSchema.typeName, 'Wrong payload type');
|
|
90
|
+
const payload = protocol.getPayload(message, SwarmResponseSchema);
|
|
91
|
+
const topic = PublicKey.from(payload.swarmKey);
|
|
92
|
+
if (!this._swarmPeers.has(topic)) {
|
|
93
|
+
log.warn('Received message from wrong topic', { topic });
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const oldPeers = this._swarmPeers.get(topic)!;
|
|
97
|
+
const timestamp = new Date(Date.parse(message.timestamp));
|
|
98
|
+
const newPeers = new ComplexSet<PublicKey>(
|
|
99
|
+
PublicKey.hash,
|
|
100
|
+
payload.peers.map(({ peerKey }) => PublicKey.from(peerKey)),
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
// Emit new available peers in the swarm.
|
|
104
|
+
for (const peer of newPeers) {
|
|
105
|
+
if (oldPeers.has(peer)) {
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
this.swarmEvent.emit({
|
|
109
|
+
topic,
|
|
110
|
+
swarmEvent: { peerAvailable: { peer: peer.asUint8Array(), since: timestamp } },
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Emit peer that left the swarm.
|
|
115
|
+
for (const peer of oldPeers.values()) {
|
|
116
|
+
if (newPeers.has(peer)) {
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
this.swarmEvent.emit({
|
|
120
|
+
topic,
|
|
121
|
+
swarmEvent: { peerLeft: { peer: peer.asUint8Array() } },
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
this._swarmPeers.set(topic, newPeers);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
@@ -3,10 +3,8 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { type Event } from '@dxos/async';
|
|
6
|
-
import { type PublicKey } from '@dxos/keys';
|
|
7
|
-
import { type SwarmEvent } from '@dxos/protocols/proto/dxos/mesh/signal';
|
|
8
6
|
|
|
9
|
-
import { type
|
|
7
|
+
import { type SignalMethods, type SignalStatus } from '../signal-methods';
|
|
10
8
|
|
|
11
9
|
/**
|
|
12
10
|
* Manages a collection of signaling clients.
|
|
@@ -17,6 +15,4 @@ export interface SignalManager extends SignalMethods {
|
|
|
17
15
|
getStatus(): SignalStatus[];
|
|
18
16
|
|
|
19
17
|
statusChanged: Event<SignalStatus[]>;
|
|
20
|
-
swarmEvent: Event<{ topic: PublicKey; swarmEvent: SwarmEvent }>;
|
|
21
|
-
onMessage: Event<Message>;
|
|
22
18
|
}
|
|
@@ -8,6 +8,7 @@ import { runTestSignalServer, type SignalServerRunner } from '@dxos/signal';
|
|
|
8
8
|
import { afterAll, beforeAll, describe, test, openAndClose } from '@dxos/test';
|
|
9
9
|
|
|
10
10
|
import { WebsocketSignalManager } from './websocket-signal-manager';
|
|
11
|
+
import { expectPeerAvailable, expectReceivedMessage } from '../testing';
|
|
11
12
|
|
|
12
13
|
describe('WebSocketSignalManager', () => {
|
|
13
14
|
let broker1: SignalServerRunner;
|
|
@@ -31,21 +32,6 @@ describe('WebSocketSignalManager', () => {
|
|
|
31
32
|
void broker2.stop();
|
|
32
33
|
});
|
|
33
34
|
|
|
34
|
-
const expectPeerAvailable = (client: WebsocketSignalManager, expectedTopic: PublicKey, peer: PublicKey) =>
|
|
35
|
-
client.swarmEvent.waitFor(
|
|
36
|
-
({ swarmEvent, topic }) =>
|
|
37
|
-
!!swarmEvent.peerAvailable && peer.equals(swarmEvent.peerAvailable.peer) && expectedTopic.equals(topic),
|
|
38
|
-
);
|
|
39
|
-
|
|
40
|
-
const expectReceivedMessage = (client: WebsocketSignalManager, expectedMessage: any) => {
|
|
41
|
-
return client.onMessage.waitFor(
|
|
42
|
-
(msg) =>
|
|
43
|
-
msg.author.equals(expectedMessage.author) &&
|
|
44
|
-
msg.recipient.equals(expectedMessage.recipient) &&
|
|
45
|
-
PublicKey.from(msg.payload.value).equals(expectedMessage.payload.value),
|
|
46
|
-
);
|
|
47
|
-
};
|
|
48
|
-
|
|
49
35
|
test('join swarm with two brokers', async () => {
|
|
50
36
|
const client1 = new WebsocketSignalManager([{ server: broker1.url() }, { server: broker2.url() }]);
|
|
51
37
|
const client2 = new WebsocketSignalManager([{ server: broker1.url() }]);
|
|
@@ -62,12 +62,9 @@ export class WebsocketSignalManager implements SignalManager {
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
// TODO(burdon): Create factory to support different variants.
|
|
65
|
-
const server = new SignalClient(
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
async (data) => this.swarmEvent.emit(data),
|
|
69
|
-
this._getMetadata,
|
|
70
|
-
);
|
|
65
|
+
const server = new SignalClient(host.server, this._getMetadata);
|
|
66
|
+
server.swarmEvent.on((data) => this.swarmEvent.emit(data));
|
|
67
|
+
server.onMessage.on((data) => this.onMessage.emit(data));
|
|
71
68
|
|
|
72
69
|
server.statusChanged.on(() => this.statusChanged.emit(this.getStatus()));
|
|
73
70
|
|
package/src/signal-methods.ts
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
// Copyright 2022 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import { type Event } from '@dxos/async';
|
|
5
6
|
import { type PublicKey } from '@dxos/keys';
|
|
6
|
-
import { type SignalState } from '@dxos/protocols/proto/dxos/mesh/signal';
|
|
7
|
+
import { type SwarmEvent, type SignalState } from '@dxos/protocols/proto/dxos/mesh/signal';
|
|
7
8
|
|
|
8
9
|
export interface Message {
|
|
9
10
|
author: PublicKey;
|
|
@@ -27,6 +28,16 @@ export type SignalStatus = {
|
|
|
27
28
|
* Message routing interface.
|
|
28
29
|
*/
|
|
29
30
|
export interface SignalMethods {
|
|
31
|
+
/**
|
|
32
|
+
* Emits when other peers join or leave the swarm.
|
|
33
|
+
*/
|
|
34
|
+
swarmEvent: Event<{ topic: PublicKey; swarmEvent: SwarmEvent }>;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Emits when a message is received.
|
|
38
|
+
*/
|
|
39
|
+
onMessage: Event<Message>;
|
|
40
|
+
|
|
30
41
|
/**
|
|
31
42
|
* Join topic on signal network, to be discoverable by other peers.
|
|
32
43
|
*/
|
package/src/testing.ts
CHANGED
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
MemorySignalManagerContext,
|
|
15
15
|
WebsocketSignalManager,
|
|
16
16
|
} from './signal-manager';
|
|
17
|
-
import { type Message } from './signal-methods';
|
|
17
|
+
import { type SignalMethods, type Message } from './signal-methods';
|
|
18
18
|
|
|
19
19
|
export type TestBuilderOptions = {
|
|
20
20
|
signalHosts?: Runtime.Services.Signal[];
|
|
@@ -97,3 +97,24 @@ export class TestPeer {
|
|
|
97
97
|
await this.signalManager.close();
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
|
+
|
|
101
|
+
export const expectPeerAvailable = (client: SignalMethods, expectedTopic: PublicKey, peer: PublicKey) =>
|
|
102
|
+
client.swarmEvent.waitFor(
|
|
103
|
+
({ swarmEvent, topic }) =>
|
|
104
|
+
!!swarmEvent.peerAvailable && peer.equals(swarmEvent.peerAvailable.peer) && expectedTopic.equals(topic),
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
export const expectPeerLeft = (client: SignalMethods, expectedTopic: PublicKey, peer: PublicKey) =>
|
|
108
|
+
client.swarmEvent.waitFor(
|
|
109
|
+
({ swarmEvent, topic }) =>
|
|
110
|
+
!!swarmEvent.peerLeft && peer.equals(swarmEvent.peerLeft.peer) && expectedTopic.equals(topic),
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
export const expectReceivedMessage = (client: SignalMethods, expectedMessage: Message) => {
|
|
114
|
+
return client.onMessage.waitFor(
|
|
115
|
+
(msg) =>
|
|
116
|
+
msg.author.equals(expectedMessage.author) &&
|
|
117
|
+
msg.recipient.equals(expectedMessage.recipient) &&
|
|
118
|
+
PublicKey.from(msg.payload.value).equals(expectedMessage.payload.value),
|
|
119
|
+
);
|
|
120
|
+
};
|