@dxos/network-manager 0.1.17 → 0.1.18

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.
Files changed (60) hide show
  1. package/dist/lib/browser/index.mjs +144 -276
  2. package/dist/lib/browser/meta.json +1 -1
  3. package/dist/lib/browser/testing/index.mjs +153 -342
  4. package/dist/lib/node/index.cjs +145 -281
  5. package/dist/lib/node/meta.json +1 -1
  6. package/dist/lib/node/testing/index.cjs +153 -345
  7. package/dist/types/src/index.d.ts +0 -1
  8. package/dist/types/src/index.d.ts.map +1 -1
  9. package/dist/types/src/network-manager.d.ts +1 -5
  10. package/dist/types/src/network-manager.d.ts.map +1 -1
  11. package/dist/types/src/swarm/connection.d.ts +4 -0
  12. package/dist/types/src/swarm/connection.d.ts.map +1 -1
  13. package/dist/types/src/swarm/peer.d.ts.map +1 -1
  14. package/dist/types/src/swarm/swarm-mapper.d.ts +1 -3
  15. package/dist/types/src/swarm/swarm-mapper.d.ts.map +1 -1
  16. package/dist/types/src/testing/index.d.ts +0 -1
  17. package/dist/types/src/testing/index.d.ts.map +1 -1
  18. package/dist/types/src/testing/test-builder.d.ts +2 -2
  19. package/dist/types/src/testing/test-builder.d.ts.map +1 -1
  20. package/dist/types/src/testing/test-wire-protocol.d.ts +14 -0
  21. package/dist/types/src/testing/test-wire-protocol.d.ts.map +1 -0
  22. package/dist/types/src/tests/basic-test-suite.d.ts.map +1 -1
  23. package/dist/types/src/tests/property-test-suite.d.ts.map +1 -1
  24. package/dist/types/src/tests/utils.d.ts.map +1 -1
  25. package/dist/types/src/transport/memory-transport.d.ts +3 -3
  26. package/dist/types/src/transport/memory-transport.d.ts.map +1 -1
  27. package/dist/types/src/wire-protocol.d.ts +0 -10
  28. package/dist/types/src/wire-protocol.d.ts.map +1 -1
  29. package/package.json +16 -18
  30. package/src/connection-log.ts +26 -26
  31. package/src/index.ts +0 -1
  32. package/src/network-manager.ts +1 -8
  33. package/src/swarm/connection.ts +12 -1
  34. package/src/swarm/peer.ts +1 -3
  35. package/src/swarm/swarm-mapper.ts +29 -31
  36. package/src/swarm/swarm.test.ts +12 -34
  37. package/src/testing/index.ts +0 -1
  38. package/src/testing/test-builder.ts +4 -7
  39. package/src/testing/test-wire-protocol.ts +44 -0
  40. package/src/tests/basic-test-suite.ts +13 -53
  41. package/src/tests/property-test-suite.ts +13 -15
  42. package/src/tests/utils.ts +10 -37
  43. package/src/transport/memory-transport.test.ts +13 -52
  44. package/src/transport/memory-transport.ts +37 -29
  45. package/src/transport/webrtc-transport-proxy.test.ts +13 -73
  46. package/src/transport/webrtc-transport.test.ts +7 -38
  47. package/src/wire-protocol.ts +0 -24
  48. package/dist/lib/browser/index.mjs.map +0 -7
  49. package/dist/lib/browser/testing/index.mjs.map +0 -7
  50. package/dist/lib/node/index.cjs.map +0 -7
  51. package/dist/lib/node/testing/index.cjs.map +0 -7
  52. package/dist/types/src/protocol-factory.d.ts +0 -36
  53. package/dist/types/src/protocol-factory.d.ts.map +0 -1
  54. package/dist/types/src/testing/test-protocol.d.ts +0 -52
  55. package/dist/types/src/testing/test-protocol.d.ts.map +0 -1
  56. package/dist/types/src/tests/presence.test.d.ts +0 -2
  57. package/dist/types/src/tests/presence.test.d.ts.map +0 -1
  58. package/src/protocol-factory.ts +0 -88
  59. package/src/testing/test-protocol.ts +0 -166
  60. package/src/tests/presence.test.ts +0 -80
@@ -8,7 +8,7 @@ import { Transform } from 'node:stream';
8
8
  import { Event, Trigger } from '@dxos/async';
9
9
  import { ErrorStream } from '@dxos/debug';
10
10
  import { PublicKey } from '@dxos/keys';
11
- import { log } from '@dxos/log';
11
+ import { log, logInfo } from '@dxos/log';
12
12
  import { Signal } from '@dxos/protocols/proto/dxos/mesh/swarm';
13
13
  import { ComplexMap } from '@dxos/util';
14
14
 
@@ -45,29 +45,34 @@ export class MemoryTransport implements Transport {
45
45
  public readonly connected = new Event<void>();
46
46
  public readonly errors = new ErrorStream();
47
47
 
48
- private readonly _id = PublicKey.random(); // TODO(burdon): Rename peerId? (Use local/remote labels in logs).
48
+ @logInfo
49
+ private readonly _instanceId = PublicKey.random(); // TODO(burdon): Rename peerId? (Use local/remote labels in logs).
50
+
49
51
  private readonly _remote = new Trigger<PublicKey>();
50
52
 
51
53
  private readonly _outgoingDelay = createStreamDelay(MEMORY_TRANSPORT_DELAY);
52
54
  private readonly _incomingDelay = createStreamDelay(MEMORY_TRANSPORT_DELAY);
53
55
 
54
56
  private _destroyed = false;
55
- private _remoteId!: PublicKey;
57
+
58
+ @logInfo
59
+ private _remoteInstanceId!: PublicKey;
60
+
56
61
  private _remoteConnection?: MemoryTransport;
57
62
 
58
63
  constructor(private readonly options: TransportOptions) {
59
- log('creating', { id: this._id });
64
+ log('creating');
60
65
 
61
- assert(!MemoryTransport._connections.has(this._id), 'Duplicate memory connection');
62
- MemoryTransport._connections.set(this._id, this);
66
+ assert(!MemoryTransport._connections.has(this._instanceId), 'Duplicate memory connection');
67
+ MemoryTransport._connections.set(this._instanceId, this);
63
68
 
64
69
  // Initiator will send a signal, the receiver will receive the unique ID and connect the streams.
65
70
  if (this.options.initiator) {
66
71
  // prettier-ignore
67
72
  setTimeout(async () => {
68
- log('sending signal', { transportId: this._id });
73
+ log('sending signal');
69
74
  void this.options.sendSignal({
70
- payload: { transportId: this._id.toHex() }
75
+ payload: { transportId: this._instanceId.toHex() }
71
76
  });
72
77
  });
73
78
  } else {
@@ -78,8 +83,8 @@ export class MemoryTransport implements Transport {
78
83
  return;
79
84
  }
80
85
 
81
- this._remoteId = remoteId;
82
- this._remoteConnection = MemoryTransport._connections.get(this._remoteId);
86
+ this._remoteInstanceId = remoteId;
87
+ this._remoteConnection = MemoryTransport._connections.get(this._remoteInstanceId);
83
88
  if (!this._remoteConnection) {
84
89
  // Remote connection was destroyed before we could connect.
85
90
  this._destroyed = true;
@@ -87,11 +92,14 @@ export class MemoryTransport implements Transport {
87
92
  return;
88
93
  }
89
94
 
90
- assert(!this._remoteConnection._remoteConnection, new Error(`Remote already connected: ${this._remoteId}`));
95
+ assert(
96
+ !this._remoteConnection._remoteConnection,
97
+ new Error(`Remote already connected: ${this._remoteInstanceId}`)
98
+ );
91
99
  this._remoteConnection._remoteConnection = this;
92
- this._remoteConnection._remoteId = this._id;
100
+ this._remoteConnection._remoteInstanceId = this._instanceId;
93
101
 
94
- log('connected', { id: this._id, remote: this._remoteId });
102
+ log('connected');
95
103
  this.options.stream
96
104
  .pipe(this._outgoingDelay)
97
105
  .pipe(this._remoteConnection.options.stream)
@@ -112,14 +120,14 @@ export class MemoryTransport implements Transport {
112
120
  }
113
121
 
114
122
  async destroy(): Promise<void> {
115
- log('closing', { id: this._id });
123
+ log('closing');
116
124
  this._destroyed = true;
117
125
 
118
- MemoryTransport._connections.delete(this._id);
126
+ MemoryTransport._connections.delete(this._instanceId);
119
127
  if (this._remoteConnection) {
120
- log('closing', { id: this._remoteId });
128
+ log('closing');
121
129
  this._remoteConnection._destroyed = true;
122
- MemoryTransport._connections.delete(this._remoteId);
130
+ MemoryTransport._connections.delete(this._remoteInstanceId);
123
131
 
124
132
  // TODO(dmaretskyi): Hypercore streams do not seem to have the unpipe method.
125
133
  // NOTE(burdon): Using readable-stream.wrap() might help (see feed-store).
@@ -135,23 +143,23 @@ export class MemoryTransport implements Transport {
135
143
  this._remoteConnection.closed.emit();
136
144
  this._remoteConnection._remoteConnection = undefined;
137
145
  this._remoteConnection = undefined;
138
- log('closed', { id: this._remoteId });
146
+ log('closed');
139
147
  }
140
148
 
141
149
  this.closed.emit();
142
- log('closed', { id: this._id });
150
+ log('closed');
143
151
  }
144
152
 
145
- signal(signal: Signal) {
146
- const { payload: json } = signal;
147
- if (json && json.transportId) {
148
- // TODO(burdon): Check open?
149
- const transportId = json.transportId as string;
150
- if (transportId) {
151
- const remoteId = PublicKey.fromHex(transportId);
152
- log('received signal', { id: this._id, remoteId });
153
- this._remote.wake(remoteId);
154
- }
153
+ signal({ payload }: Signal) {
154
+ log('received signal', { payload });
155
+ if (!payload?.transportId) {
156
+ return;
157
+ }
158
+ // TODO(burdon): Check open?
159
+ const transportId = payload.transportId as string;
160
+ if (transportId) {
161
+ const remoteId = PublicKey.fromHex(transportId);
162
+ this._remote.wake(remoteId);
155
163
  }
156
164
  }
157
165
  }
@@ -5,27 +5,21 @@
5
5
  // @dxos/test platform=nodejs
6
6
 
7
7
  import expect from 'expect';
8
- import { Duplex } from 'stream';
9
- import waitForExpect from 'wait-for-expect';
10
8
 
11
- import { sleep } from '@dxos/async';
12
- import { discoveryKey } from '@dxos/crypto';
13
- import { PublicKey } from '@dxos/keys';
14
- import { Protocol } from '@dxos/mesh-protocol';
9
+ import { sleep, TestStream } from '@dxos/async';
15
10
  import { schema } from '@dxos/protocols';
16
11
  import { BridgeService } from '@dxos/protocols/proto/dxos/mesh/bridge';
17
12
  import { Signal } from '@dxos/protocols/proto/dxos/mesh/swarm';
18
13
  import { createLinkedPorts, createProtoRpcPeer, ProtoRpcPeer } from '@dxos/rpc';
19
- import { afterAll, beforeAll, describe, test, afterTest } from '@dxos/test';
14
+ import { afterAll, afterTest, beforeAll, describe, test } from '@dxos/test';
20
15
 
21
- import { TestProtocolPlugin, testProtocolProvider } from '../testing';
22
16
  import { WebRTCTransportProxy } from './webrtc-transport-proxy';
23
17
  import { WebRTCTransportService } from './webrtc-transport-service';
24
18
 
25
19
  describe('WebRTCTransportProxy', () => {
26
20
  const setupProxy = async ({
27
21
  initiator = true,
28
- stream = new Duplex({ write: () => {}, read: () => {} }),
22
+ stream = new TestStream(),
29
23
  sendSignal = async () => {}
30
24
  }: {
31
25
  initiator?: boolean;
@@ -99,18 +93,10 @@ describe('WebRTCTransportProxy', () => {
99
93
  .retries(3);
100
94
 
101
95
  test('establish connection and send data through with protocol', async () => {
102
- const topic = PublicKey.random();
103
- const peer1Id = PublicKey.random();
104
- const peer2Id = PublicKey.random();
105
-
106
- const plugin1 = new TestProtocolPlugin(peer1Id.asBuffer());
107
- const protocolProvider1 = testProtocolProvider(topic.asBuffer(), peer1Id, plugin1);
96
+ const stream1 = new TestStream();
108
97
  const { webRTCTransportProxy: connection1 } = await setupProxy({
109
98
  initiator: true,
110
- stream: protocolProvider1({
111
- channel: discoveryKey(topic),
112
- initiator: true
113
- }).stream,
99
+ stream: stream1,
114
100
  sendSignal: async (signal) => {
115
101
  await sleep(10);
116
102
  await connection2.signal(signal);
@@ -118,36 +104,17 @@ describe('WebRTCTransportProxy', () => {
118
104
  });
119
105
  afterTest(() => connection1.errors.assertNoUnhandledErrors());
120
106
 
121
- const plugin2 = new TestProtocolPlugin(peer2Id.asBuffer());
122
- const protocolProvider2 = testProtocolProvider(topic.asBuffer(), peer2Id, plugin2);
107
+ const stream2 = new TestStream();
123
108
  const { webRTCTransportProxy: connection2 } = await setupProxy({
124
109
  initiator: false,
125
- stream: protocolProvider2({
126
- channel: discoveryKey(topic),
127
- initiator: false
128
- }).stream,
110
+ stream: stream2,
129
111
  sendSignal: async (signal) => {
130
112
  await sleep(10);
131
113
  await connection1.signal(signal);
132
114
  }
133
115
  });
134
116
  afterTest(() => connection2.errors.assertNoUnhandledErrors());
135
-
136
- const received: any[] = [];
137
- const mockReceive = (p: Protocol, s: string) => {
138
- received.push(p, s);
139
- return undefined;
140
- };
141
- plugin1.on('receive', mockReceive);
142
-
143
- plugin2.on('connect', async (protocol) => {
144
- await plugin2.send(peer1Id.asBuffer(), '{"message": "Hello"}');
145
- });
146
- await waitForExpect(() => {
147
- expect(received.length).toBe(2);
148
- expect(received[0]).toBeInstanceOf(Protocol);
149
- expect(received[1]).toBe('{"message": "Hello"}');
150
- });
117
+ await TestStream.assertConnectivity(stream1, stream2);
151
118
  })
152
119
  .timeout(2_000)
153
120
  .retries(3);
@@ -192,18 +159,10 @@ describe('WebRTCTransportProxy', () => {
192
159
  });
193
160
 
194
161
  test('establish connection and send data through with protocol', async () => {
195
- const topic = PublicKey.random();
196
- const peer1Id = PublicKey.random();
197
- const peer2Id = PublicKey.random();
198
-
199
- const plugin1 = new TestProtocolPlugin(peer1Id.asBuffer());
200
- const protocolProvider1 = testProtocolProvider(topic.asBuffer(), peer1Id, plugin1);
162
+ const stream1 = new TestStream();
201
163
  const proxy1 = new WebRTCTransportProxy({
202
164
  initiator: true,
203
- stream: protocolProvider1({
204
- channel: discoveryKey(topic),
205
- initiator: true
206
- }).stream,
165
+ stream: stream1,
207
166
  sendSignal: async (signal) => {
208
167
  await sleep(10);
209
168
  await proxy2.signal(signal);
@@ -212,14 +171,10 @@ describe('WebRTCTransportProxy', () => {
212
171
  });
213
172
  afterTest(() => proxy1.errors.assertNoUnhandledErrors());
214
173
 
215
- const plugin2 = new TestProtocolPlugin(peer2Id.asBuffer());
216
- const protocolProvider2 = testProtocolProvider(topic.asBuffer(), peer2Id, plugin2);
174
+ const stream2 = new TestStream();
217
175
  const proxy2 = new WebRTCTransportProxy({
218
176
  initiator: false,
219
- stream: protocolProvider2({
220
- channel: discoveryKey(topic),
221
- initiator: false
222
- }).stream,
177
+ stream: stream2,
223
178
  sendSignal: async (signal) => {
224
179
  await sleep(10);
225
180
  await proxy1.signal(signal);
@@ -228,22 +183,7 @@ describe('WebRTCTransportProxy', () => {
228
183
  });
229
184
  afterTest(() => proxy2.errors.assertNoUnhandledErrors());
230
185
 
231
- const received: any[] = [];
232
- const mockReceive = (p: Protocol, s: string) => {
233
- received.push(p, s);
234
- return undefined;
235
- };
236
- plugin1.on('receive', mockReceive);
237
-
238
- plugin2.on('connect', async (protocol) => {
239
- await plugin2.send(peer1Id.asBuffer(), '{"message": "Hello"}');
240
- });
241
-
242
- await waitForExpect(() => {
243
- expect(received.length).toBe(2);
244
- expect(received[0]).toBeInstanceOf(Protocol);
245
- expect(received[1]).toBe('{"message": "Hello"}');
246
- });
186
+ await TestStream.assertConnectivity(stream1, stream2);
247
187
  })
248
188
  .timeout(5_000)
249
189
  .retries(3);
@@ -4,15 +4,10 @@
4
4
 
5
5
  import expect from 'expect';
6
6
  import { Duplex } from 'stream';
7
- import waitForExpect from 'wait-for-expect';
8
7
 
9
- import { sleep } from '@dxos/async';
10
- import { discoveryKey } from '@dxos/crypto';
11
- import { PublicKey } from '@dxos/keys';
12
- import { Protocol } from '@dxos/mesh-protocol';
13
- import { describe, test, afterTest } from '@dxos/test';
8
+ import { sleep, TestStream } from '@dxos/async';
9
+ import { afterTest, describe, test } from '@dxos/test';
14
10
 
15
- import { TestProtocolPlugin, testProtocolProvider } from '../testing';
16
11
  import { WebRTCTransport } from './webrtc-transport';
17
12
 
18
13
  describe('WebRTCTransport', () => {
@@ -40,18 +35,10 @@ describe('WebRTCTransport', () => {
40
35
  .retries(3);
41
36
 
42
37
  test('establish connection and send data through with protocol', async () => {
43
- const topic = PublicKey.random();
44
- const peer1Id = PublicKey.random();
45
- const peer2Id = PublicKey.random();
46
-
47
- const plugin1 = new TestProtocolPlugin(peer1Id.asBuffer());
48
- const protocolProvider1 = testProtocolProvider(topic.asBuffer(), peer1Id, plugin1);
38
+ const stream1 = new TestStream();
49
39
  const connection1 = new WebRTCTransport({
50
40
  initiator: true,
51
- stream: protocolProvider1({
52
- channel: discoveryKey(topic),
53
- initiator: true
54
- }).stream,
41
+ stream: stream1,
55
42
  sendSignal: async (signal) => {
56
43
  await sleep(10);
57
44
  await connection2.signal(signal);
@@ -60,14 +47,10 @@ describe('WebRTCTransport', () => {
60
47
  afterTest(() => connection1.destroy());
61
48
  afterTest(() => connection1.errors.assertNoUnhandledErrors());
62
49
 
63
- const plugin2 = new TestProtocolPlugin(peer2Id.asBuffer());
64
- const protocolProvider2 = testProtocolProvider(topic.asBuffer(), peer2Id, plugin2);
50
+ const stream2 = new TestStream();
65
51
  const connection2 = new WebRTCTransport({
66
52
  initiator: false,
67
- stream: protocolProvider2({
68
- channel: discoveryKey(topic),
69
- initiator: false
70
- }).stream,
53
+ stream: stream2,
71
54
  sendSignal: async (signal) => {
72
55
  await sleep(10);
73
56
  await connection1.signal(signal);
@@ -76,21 +59,7 @@ describe('WebRTCTransport', () => {
76
59
  afterTest(() => connection2.destroy());
77
60
  afterTest(() => connection2.errors.assertNoUnhandledErrors());
78
61
 
79
- const received: any[] = [];
80
- const mockReceive = (p: Protocol, s: string) => {
81
- received.push(p, s);
82
- return undefined;
83
- };
84
- plugin1.on('receive', mockReceive);
85
- plugin2.on('connect', async (protocol) => {
86
- await plugin2.send(peer1Id.asBuffer(), '{"message": "Hello"}');
87
- });
88
-
89
- await waitForExpect(() => {
90
- expect(received.length).toBe(2);
91
- expect(received[0]).toBeInstanceOf(Protocol);
92
- expect(received[1]).toBe('{"message": "Hello"}');
93
- });
62
+ await TestStream.assertConnectivity(stream1, stream2);
94
63
  })
95
64
  .timeout(2_000)
96
65
  .retries(3);
@@ -4,13 +4,9 @@
4
4
 
5
5
  import { Duplex } from 'node:stream';
6
6
 
7
- import { discoveryKey } from '@dxos/crypto';
8
7
  import { PublicKey } from '@dxos/keys';
9
- import { Protocol } from '@dxos/mesh-protocol';
10
8
  import { Teleport } from '@dxos/teleport';
11
9
 
12
- import { MeshProtocolProvider } from './protocol-factory';
13
-
14
10
  export type WireProtocolParams = {
15
11
  initiator: boolean;
16
12
  localPeerId: PublicKey;
@@ -27,30 +23,10 @@ export type WireProtocolProvider = (params: WireProtocolParams) => WireProtocol;
27
23
  export interface WireProtocol {
28
24
  stream: Duplex;
29
25
 
30
- /**
31
- * @deprecated Only for devtools comapatibility.
32
- */
33
- protocol?: Protocol;
34
-
35
26
  initialize(): Promise<void>;
36
27
  destroy(): Promise<void>;
37
28
  }
38
29
 
39
- /**
40
- * @deprecated
41
- */
42
- export const adaptProtocolProvider =
43
- (factory: MeshProtocolProvider): WireProtocolProvider =>
44
- ({ initiator, localPeerId, remotePeerId, topic }) => {
45
- const protocol = factory({ channel: discoveryKey(topic), initiator });
46
- return {
47
- initialize: () => protocol.open(),
48
- destroy: () => protocol.close(),
49
- stream: protocol.stream,
50
- protocol
51
- };
52
- };
53
-
54
30
  /**
55
31
  * Create a wire-protocol provider backed by a teleport instance.
56
32
  * @param onConnection Called after teleport is initialized for the session. Protocol extensions could be attached here.