@dxos/edge-client 0.6.12-main.ed7cda7 → 0.6.12-staging.0b4bb48

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 (49) hide show
  1. package/dist/lib/browser/index.mjs +157 -57
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node/index.cjs +154 -56
  5. package/dist/lib/node/index.cjs.map +4 -4
  6. package/dist/lib/node/meta.json +1 -1
  7. package/dist/types/src/defs.d.ts.map +1 -1
  8. package/dist/types/src/edge-client.d.ts +2 -3
  9. package/dist/types/src/edge-client.d.ts.map +1 -1
  10. package/dist/types/src/errors.d.ts +1 -4
  11. package/dist/types/src/errors.d.ts.map +1 -1
  12. package/dist/types/src/index.d.ts +0 -1
  13. package/dist/types/src/index.d.ts.map +1 -1
  14. package/dist/types/src/protocol.d.ts +2 -2
  15. package/dist/types/src/protocol.d.ts.map +1 -1
  16. package/dist/types/src/test-utils.d.ts +11 -0
  17. package/dist/types/src/test-utils.d.ts.map +1 -0
  18. package/package.json +14 -26
  19. package/src/defs.ts +3 -2
  20. package/src/edge-client.test.ts +11 -11
  21. package/src/edge-client.ts +8 -17
  22. package/src/errors.ts +2 -8
  23. package/src/index.ts +0 -1
  24. package/src/persistent-lifecycle.test.ts +2 -2
  25. package/src/protocol.test.ts +2 -1
  26. package/src/protocol.ts +2 -2
  27. package/src/test-utils.ts +49 -0
  28. package/src/websocket.test.ts +4 -5
  29. package/dist/lib/browser/chunk-ZWJXA37R.mjs +0 -113
  30. package/dist/lib/browser/chunk-ZWJXA37R.mjs.map +0 -7
  31. package/dist/lib/browser/testing/index.mjs +0 -122
  32. package/dist/lib/browser/testing/index.mjs.map +0 -7
  33. package/dist/lib/node/chunk-ANV2HBEH.cjs +0 -136
  34. package/dist/lib/node/chunk-ANV2HBEH.cjs.map +0 -7
  35. package/dist/lib/node/testing/index.cjs +0 -152
  36. package/dist/lib/node/testing/index.cjs.map +0 -7
  37. package/dist/lib/node-esm/chunk-HNVT57AU.mjs +0 -115
  38. package/dist/lib/node-esm/chunk-HNVT57AU.mjs.map +0 -7
  39. package/dist/lib/node-esm/index.mjs +0 -378
  40. package/dist/lib/node-esm/index.mjs.map +0 -7
  41. package/dist/lib/node-esm/meta.json +0 -1
  42. package/dist/lib/node-esm/testing/index.mjs +0 -123
  43. package/dist/lib/node-esm/testing/index.mjs.map +0 -7
  44. package/dist/types/src/testing/index.d.ts +0 -2
  45. package/dist/types/src/testing/index.d.ts.map +0 -1
  46. package/dist/types/src/testing/test-utils.d.ts +0 -20
  47. package/dist/types/src/testing/test-utils.d.ts.map +0 -1
  48. package/src/testing/index.ts +0 -5
  49. package/src/testing/test-utils.ts +0 -111
@@ -1 +1 @@
1
- {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../../src/protocol.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,GAAG,EAAU,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,KAAK,OAAO,EAAiB,KAAK,UAAU,EAAE,MAAM,4CAA4C,CAAC;AAG1G,MAAM,MAAM,QAAQ,GAAG,GAAG,CAAC,gBAAgB,CAAC,OAAO,UAAU,CAAC,CAAC;AAE/D,eAAO,MAAM,WAAW,aAAc,MAAM,WAAsC,CAAC;AAEnF;;GAEG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAe;gBAEjC,KAAK,EAAE,GAAG,CAAC,WAAW,EAAE;IAIpC,IAAI,YAAY,IAAI,GAAG,CAAC,QAAQ,CAE/B;IAED,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,GAAG;IAQ7B;;OAEG;IACH,UAAU,CAAC,IAAI,SAAS,GAAG,CAAC,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,GAAG,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC;IAa9F;;OAEG;IACH,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS;IASpD;;OAEG;IACH,aAAa,CAAC,IAAI,SAAS,GAAG,CAAC,WAAW,EACxC,IAAI,EAAE,IAAI,EACV,EACE,MAAM,EACN,MAAM,EACN,OAAO,EACP,SAAS,GACV,EAAE;QACD,MAAM,CAAC,EAAE,QAAQ,CAAC;QAClB,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC;QACpB,OAAO,CAAC,EAAE,GAAG,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;QACrC,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB;CAUJ;AAED;;GAEG;AACH,eAAO,MAAM,YAAY,SAAgB,GAAG,KAAG,OAAO,CAAC,UAAU,CAYhE,CAAC"}
1
+ {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../../src/protocol.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,GAAG,EAAU,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,KAAK,OAAO,EAAiB,KAAK,IAAI,IAAI,SAAS,EAAE,MAAM,4CAA4C,CAAC;AAGjH,MAAM,MAAM,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;AAE1C,eAAO,MAAM,WAAW,aAAc,MAAM,WAAsC,CAAC;AAEnF;;GAEG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAe;gBAEjC,KAAK,EAAE,GAAG,CAAC,WAAW,EAAE;IAIpC,IAAI,YAAY,IAAI,GAAG,CAAC,QAAQ,CAE/B;IAED,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,GAAG;IAQ7B;;OAEG;IACH,UAAU,CAAC,IAAI,SAAS,GAAG,CAAC,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,GAAG,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC;IAa9F;;OAEG;IACH,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS;IASpD;;OAEG;IACH,aAAa,CAAC,IAAI,SAAS,GAAG,CAAC,WAAW,EACxC,IAAI,EAAE,IAAI,EACV,EACE,MAAM,EACN,MAAM,EACN,OAAO,EACP,SAAS,GACV,EAAE;QACD,MAAM,CAAC,EAAE,QAAQ,CAAC;QAClB,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC;QACpB,OAAO,CAAC,EAAE,GAAG,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;QACrC,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB;CAUJ;AAED;;GAEG;AACH,eAAO,MAAM,YAAY,SAAgB,GAAG,KAAG,OAAO,CAAC,UAAU,CAYhE,CAAC"}
@@ -0,0 +1,11 @@
1
+ import WebSocket from 'isomorphic-ws';
2
+ export declare const DEFAULT_PORT = 8080;
3
+ export declare const createTestWsServer: (port?: number) => Promise<{
4
+ server: WebSocket.Server;
5
+ /**
6
+ * Close the server connection.
7
+ */
8
+ error: () => Promise<void>;
9
+ endpoint: string;
10
+ }>;
11
+ //# sourceMappingURL=test-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-utils.d.ts","sourceRoot":"","sources":["../../../src/test-utils.ts"],"names":[],"mappings":"AAIA,OAAO,SAAS,MAAM,eAAe,CAAC;AAWtC,eAAO,MAAM,YAAY,OAAO,CAAC;AAEjC,eAAO,MAAM,kBAAkB;;IAsB3B;;OAEG;;;EAON,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/edge-client",
3
- "version": "0.6.12-main.ed7cda7",
3
+ "version": "0.6.12-staging.0b4bb48",
4
4
  "description": "EDGE Client",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -10,27 +10,14 @@
10
10
  ".": {
11
11
  "browser": "./dist/lib/browser/index.mjs",
12
12
  "node": {
13
- "require": "./dist/lib/node/index.cjs",
14
- "default": "./dist/lib/node-esm/index.mjs"
13
+ "default": "./dist/lib/node/index.cjs"
15
14
  },
16
15
  "types": "./dist/types/src/index.d.ts"
17
- },
18
- "./testing": {
19
- "browser": "./dist/lib/browser/testing/index.mjs",
20
- "node": {
21
- "require": "./dist/lib/node/testing/index.cjs",
22
- "default": "./dist/lib/node-esm/testing/index.mjs"
23
- },
24
- "types": "./dist/types/src/testing/index.d.ts"
25
16
  }
26
17
  },
27
18
  "types": "dist/types/src/index.d.ts",
28
19
  "typesVersions": {
29
- "*": {
30
- "testing": [
31
- "dist/types/src/testing/index.d.ts"
32
- ]
33
- }
20
+ "*": {}
34
21
  },
35
22
  "files": [
36
23
  "dist",
@@ -38,20 +25,21 @@
38
25
  "README.md"
39
26
  ],
40
27
  "dependencies": {
28
+ "@bufbuild/protobuf": "^2.0.0",
41
29
  "isomorphic-ws": "^5.0.0",
42
30
  "ws": "^8.14.2",
43
- "@dxos/async": "0.6.12-main.ed7cda7",
44
- "@dxos/context": "0.6.12-main.ed7cda7",
45
- "@dxos/debug": "0.6.12-main.ed7cda7",
46
- "@dxos/invariant": "0.6.12-main.ed7cda7",
47
- "@dxos/log": "0.6.12-main.ed7cda7",
48
- "@dxos/node-std": "0.6.12-main.ed7cda7",
49
- "@dxos/protocols": "0.6.12-main.ed7cda7",
50
- "@dxos/util": "0.6.12-main.ed7cda7"
31
+ "@dxos/async": "0.6.12-staging.0b4bb48",
32
+ "@dxos/context": "0.6.12-staging.0b4bb48",
33
+ "@dxos/invariant": "0.6.12-staging.0b4bb48",
34
+ "@dxos/debug": "0.6.12-staging.0b4bb48",
35
+ "@dxos/node-std": "0.6.12-staging.0b4bb48",
36
+ "@dxos/util": "0.6.12-staging.0b4bb48",
37
+ "@dxos/protocols": "0.6.12-staging.0b4bb48",
38
+ "@dxos/log": "0.6.12-staging.0b4bb48"
51
39
  },
52
40
  "devDependencies": {
53
- "@dxos/keys": "0.6.12-main.ed7cda7",
54
- "@dxos/test-utils": "0.6.12-main.ed7cda7"
41
+ "jest-websocket-mock": "^2.5.0",
42
+ "@dxos/keys": "0.6.12-staging.0b4bb48"
55
43
  },
56
44
  "publishConfig": {
57
45
  "access": "public"
package/src/defs.ts CHANGED
@@ -2,9 +2,10 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { bufWkt } from '@dxos/protocols/buf';
5
+ import { AnySchema } from '@bufbuild/protobuf/wkt';
6
+
6
7
  import { SwarmRequestSchema, SwarmResponseSchema, TextMessageSchema } from '@dxos/protocols/buf/dxos/edge/messenger_pb';
7
8
 
8
9
  import { Protocol } from './protocol';
9
10
 
10
- export const protocol = new Protocol([SwarmRequestSchema, SwarmResponseSchema, TextMessageSchema, bufWkt.AnySchema]);
11
+ export const protocol = new Protocol([SwarmRequestSchema, SwarmResponseSchema, TextMessageSchema, AnySchema]);
@@ -2,23 +2,24 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { test, expect, describe, onTestFinished } from 'vitest';
5
+ import chai, { expect } from 'chai';
6
+ import chaiAsPromised from 'chai-as-promised';
6
7
 
7
8
  import { PublicKey } from '@dxos/keys';
8
9
  import { TextMessageSchema } from '@dxos/protocols/buf/dxos/edge/messenger_pb';
9
- import { openAndClose } from '@dxos/test-utils';
10
+ import { test, describe, openAndClose } from '@dxos/test';
10
11
 
11
12
  import { protocol } from './defs';
12
13
  import { EdgeClient } from './edge-client';
13
- import { createTestEdgeWsServer } from './testing';
14
+ import { createTestWsServer } from './test-utils';
15
+
16
+ chai.use(chaiAsPromised);
14
17
 
15
18
  describe('EdgeClient', () => {
16
19
  const textMessage = (message: string) => protocol.createMessage(TextMessageSchema, { payload: { message } });
17
20
 
18
21
  test('reconnects on error', async () => {
19
- const { closeConnection, endpoint, cleanup } = await createTestEdgeWsServer(8001);
20
- onTestFinished(cleanup);
21
-
22
+ const { error: serverError, endpoint } = await createTestWsServer();
22
23
  const id = PublicKey.random().toHex();
23
24
  const client = new EdgeClient(id, id, { socketEndpoint: endpoint });
24
25
  await openAndClose(client);
@@ -26,14 +27,13 @@ describe('EdgeClient', () => {
26
27
  expect(client.isOpen).is.true;
27
28
 
28
29
  const reconnected = client.reconnect.waitForCount(1);
29
- await closeConnection();
30
+ await serverError();
30
31
  await reconnected;
31
- await expect(client.send(textMessage('Hello world 2'))).resolves.not.toThrow();
32
+ await expect(client.send(textMessage('Hello world 2'))).to.be.fulfilled;
32
33
  });
33
34
 
34
35
  test('set identity reconnects', async () => {
35
- const { endpoint, cleanup } = await createTestEdgeWsServer(8002);
36
- onTestFinished(cleanup);
36
+ const { endpoint } = await createTestWsServer();
37
37
 
38
38
  const id = PublicKey.random().toHex();
39
39
  const client = new EdgeClient(id, id, { socketEndpoint: endpoint });
@@ -45,6 +45,6 @@ describe('EdgeClient', () => {
45
45
  const reconnected = client.reconnect.waitForCount(1);
46
46
  client.setIdentity({ peerKey: newId, identityKey: newId });
47
47
  await reconnected;
48
- await expect(client.send(textMessage('Hello world 2'))).resolves.not.toThrow();
48
+ await expect(client.send(textMessage('Hello world 2'))).to.be.fulfilled;
49
49
  });
50
50
  });
@@ -6,12 +6,13 @@ import WebSocket from 'isomorphic-ws';
6
6
 
7
7
  import { Trigger, Event, scheduleTaskInterval, scheduleTask, TriggerState } from '@dxos/async';
8
8
  import { Context, LifecycleState, Resource, type Lifecycle } from '@dxos/context';
9
+ import { invariant } from '@dxos/invariant';
9
10
  import { log } from '@dxos/log';
10
11
  import { buf } from '@dxos/protocols/buf';
11
12
  import { type Message, MessageSchema } from '@dxos/protocols/buf/dxos/edge/messenger_pb';
12
13
 
13
14
  import { protocol } from './defs';
14
- import { EdgeConnectionClosedError, EdgeIdentityChangedError } from './errors';
15
+ import { WebsocketClosedError } from './errors';
15
16
  import { PersistentLifecycle } from './persistent-lifecycle';
16
17
  import { type Protocol, toUint8Array } from './protocol';
17
18
 
@@ -21,7 +22,6 @@ const SIGNAL_KEEPALIVE_INTERVAL = 5_000;
21
22
  export type MessageListener = (message: Message) => void | Promise<void>;
22
23
 
23
24
  export interface EdgeConnection extends Required<Lifecycle> {
24
- connected: Event;
25
25
  reconnect: Event;
26
26
 
27
27
  get info(): any;
@@ -43,8 +43,7 @@ export type MessengerConfig = {
43
43
  * Messenger client.
44
44
  */
45
45
  export class EdgeClient extends Resource implements EdgeConnection {
46
- public readonly reconnect = new Event();
47
- public readonly connected = new Event();
46
+ public reconnect = new Event();
48
47
  private readonly _persistentLifecycle = new PersistentLifecycle({
49
48
  start: async () => this._openWebSocket(),
50
49
  stop: async () => this._closeWebSocket(),
@@ -52,6 +51,7 @@ export class EdgeClient extends Resource implements EdgeConnection {
52
51
  });
53
52
 
54
53
  private readonly _listeners = new Set<MessageListener>();
54
+ private readonly _protocol: Protocol;
55
55
  private _ready = new Trigger();
56
56
  private _ws?: WebSocket = undefined;
57
57
  private _keepaliveCtx?: Context = undefined;
@@ -63,6 +63,7 @@ export class EdgeClient extends Resource implements EdgeConnection {
63
63
  private readonly _config: MessengerConfig,
64
64
  ) {
65
65
  super();
66
+ this._protocol = this._config.protocol ?? protocol;
66
67
  }
67
68
 
68
69
  // TODO(burdon): Attach logging.
@@ -118,7 +119,6 @@ export class EdgeClient extends Resource implements EdgeConnection {
118
119
  this._ws.onopen = () => {
119
120
  log('opened', this.info);
120
121
  this._ready.wake();
121
- this.connected.emit();
122
122
  };
123
123
  this._ws.onclose = () => {
124
124
  log('closed', this.info);
@@ -170,7 +170,7 @@ export class EdgeClient extends Resource implements EdgeConnection {
170
170
  return;
171
171
  }
172
172
  try {
173
- this._ready.throw(this.isOpen ? new EdgeIdentityChangedError() : new EdgeConnectionClosedError());
173
+ this._ready.throw(new WebsocketClosedError());
174
174
  this._ready.reset();
175
175
  void this._keepaliveCtx?.dispose();
176
176
  this._keepaliveCtx = undefined;
@@ -197,19 +197,10 @@ export class EdgeClient extends Resource implements EdgeConnection {
197
197
  */
198
198
  public async send(message: Message): Promise<void> {
199
199
  if (this._ready.state !== TriggerState.RESOLVED) {
200
- log('waiting for websocket to become ready');
201
200
  await this._ready.wait({ timeout: this._config.timeout ?? DEFAULT_TIMEOUT });
202
201
  }
203
- if (!this._ws) {
204
- throw new EdgeConnectionClosedError();
205
- }
206
- if (
207
- message.source &&
208
- (message.source.peerKey !== this._peerKey || message.source.identityKey !== this.identityKey)
209
- ) {
210
- throw new EdgeIdentityChangedError();
211
- }
212
-
202
+ invariant(this._ws);
203
+ invariant(!message.source || message.source.peerKey === this._peerKey);
213
204
  log('sending...', { peerKey: this._peerKey, payload: protocol.getPayloadType(message) });
214
205
  this._ws.send(buf.toBinary(MessageSchema, message));
215
206
  }
package/src/errors.ts CHANGED
@@ -2,14 +2,8 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- export class EdgeConnectionClosedError extends Error {
5
+ export class WebsocketClosedError extends Error {
6
6
  constructor() {
7
- super('Edge connection closed.');
8
- }
9
- }
10
-
11
- export class EdgeIdentityChangedError extends Error {
12
- constructor() {
13
- super('Edge identity changed.');
7
+ super('WebSocket connection closed');
14
8
  }
15
9
  }
package/src/index.ts CHANGED
@@ -7,4 +7,3 @@ export * from '@dxos/protocols/buf/dxos/edge/messenger_pb';
7
7
  export * from './edge-client';
8
8
  export * from './defs';
9
9
  export * from './protocol';
10
- export * from './errors';
@@ -2,11 +2,11 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { describe, expect, test } from 'vitest';
5
+ import { expect } from 'chai';
6
6
 
7
7
  import { sleep, Trigger } from '@dxos/async';
8
8
  import { log } from '@dxos/log';
9
- import { openAndClose } from '@dxos/test-utils';
9
+ import { describe, openAndClose, test } from '@dxos/test';
10
10
 
11
11
  import { PersistentLifecycle } from './persistent-lifecycle';
12
12
 
@@ -2,7 +2,7 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { describe, expect, test } from 'vitest';
5
+ import { expect } from 'chai';
6
6
 
7
7
  import { buf } from '@dxos/protocols/buf';
8
8
  import {
@@ -11,6 +11,7 @@ import {
11
11
  SwarmRequestSchema,
12
12
  SwarmResponseSchema,
13
13
  } from '@dxos/protocols/buf/dxos/edge/messenger_pb';
14
+ import { describe, test } from '@dxos/test';
14
15
 
15
16
  import { Protocol } from './protocol';
16
17
 
package/src/protocol.ts CHANGED
@@ -4,10 +4,10 @@
4
4
 
5
5
  import { invariant } from '@dxos/invariant';
6
6
  import { buf, bufWkt } from '@dxos/protocols/buf';
7
- import { type Message, MessageSchema, type PeerSchema } from '@dxos/protocols/buf/dxos/edge/messenger_pb';
7
+ import { type Message, MessageSchema, type Peer as PeerProto } from '@dxos/protocols/buf/dxos/edge/messenger_pb';
8
8
  import { bufferToArray } from '@dxos/util';
9
9
 
10
- export type PeerData = buf.MessageInitShape<typeof PeerSchema>;
10
+ export type PeerData = Partial<PeerProto>;
11
11
 
12
12
  export const getTypename = (typeName: string) => `type.googleapis.com/${typeName}`;
13
13
 
@@ -0,0 +1,49 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import WebSocket from 'isomorphic-ws';
6
+
7
+ import { Trigger } from '@dxos/async';
8
+ import { log } from '@dxos/log';
9
+ import { buf } from '@dxos/protocols/buf';
10
+ import { MessageSchema, TextMessageSchema } from '@dxos/protocols/buf/dxos/edge/messenger_pb';
11
+ import { afterTest } from '@dxos/test';
12
+
13
+ import { protocol } from './defs';
14
+ import { toUint8Array } from './protocol';
15
+
16
+ export const DEFAULT_PORT = 8080;
17
+
18
+ export const createTestWsServer = async (port = DEFAULT_PORT) => {
19
+ const server = new WebSocket.Server({ port });
20
+ let connection: WebSocket;
21
+ const closeTrigger = new Trigger();
22
+ server.on('connection', (ws) => {
23
+ connection = ws;
24
+ ws.on('error', (err) => log.catch(err));
25
+ ws.on('message', async (data) => {
26
+ if (String(data) === '__ping__') {
27
+ ws.send('__pong__');
28
+ return;
29
+ }
30
+ log('message', {
31
+ payload: protocol.getPayload(buf.fromBinary(MessageSchema, await toUint8Array(data)), TextMessageSchema),
32
+ });
33
+ });
34
+ ws.on('close', () => closeTrigger.wake());
35
+ });
36
+
37
+ afterTest(() => server.close());
38
+ return {
39
+ server,
40
+ /**
41
+ * Close the server connection.
42
+ */
43
+ error: async () => {
44
+ connection.close(1011);
45
+ await closeTrigger.wait();
46
+ },
47
+ endpoint: `ws://localhost:${port}`,
48
+ };
49
+ };
@@ -2,18 +2,17 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
+ import { expect } from 'chai';
5
6
  import WebSocket from 'isomorphic-ws';
6
- import { describe, expect, test, onTestFinished } from 'vitest';
7
7
 
8
8
  import { Trigger, TriggerState } from '@dxos/async';
9
+ import { describe, test } from '@dxos/test';
9
10
 
10
- import { createTestEdgeWsServer } from './testing';
11
+ import { createTestWsServer } from './test-utils';
11
12
 
12
13
  describe('WebSocket', () => {
13
14
  test('swap `onclose` handler ', async () => {
14
- const { endpoint, cleanup } = await createTestEdgeWsServer(8003);
15
- onTestFinished(cleanup);
16
-
15
+ const { endpoint } = await createTestWsServer();
17
16
  const ws = new WebSocket(endpoint);
18
17
  const opened = new Trigger();
19
18
  ws.onopen = () => {
@@ -1,113 +0,0 @@
1
- // packages/core/mesh/edge-client/src/protocol.ts
2
- import { invariant } from "@dxos/invariant";
3
- import { buf, bufWkt } from "@dxos/protocols/buf";
4
- import { MessageSchema } from "@dxos/protocols/buf/dxos/edge/messenger_pb";
5
- import { bufferToArray } from "@dxos/util";
6
- var __dxlog_file = "/home/runner/work/dxos/dxos/packages/core/mesh/edge-client/src/protocol.ts";
7
- var getTypename = (typeName) => `type.googleapis.com/${typeName}`;
8
- var Protocol = class {
9
- constructor(types) {
10
- this._typeRegistry = buf.createRegistry(...types);
11
- }
12
- get typeRegistry() {
13
- return this._typeRegistry;
14
- }
15
- toJson(message) {
16
- try {
17
- return buf.toJson(MessageSchema, message, {
18
- registry: this.typeRegistry
19
- });
20
- } catch (err) {
21
- return {
22
- type: this.getPayloadType(message)
23
- };
24
- }
25
- }
26
- /**
27
- * Return the payload with the given type.
28
- */
29
- getPayload(message, type) {
30
- invariant(message.payload, void 0, {
31
- F: __dxlog_file,
32
- L: 40,
33
- S: this,
34
- A: [
35
- "message.payload",
36
- ""
37
- ]
38
- });
39
- const payloadTypename = this.getPayloadType(message);
40
- if (type && type.typeName !== payloadTypename) {
41
- throw new Error(`Unexpected payload type: ${payloadTypename}; expected ${type.typeName}`);
42
- }
43
- invariant(bufWkt.anyIs(message.payload, type), `Unexpected payload type: ${payloadTypename}}`, {
44
- F: __dxlog_file,
45
- L: 46,
46
- S: this,
47
- A: [
48
- "bufWkt.anyIs(message.payload, type)",
49
- "`Unexpected payload type: ${payloadTypename}}`"
50
- ]
51
- });
52
- const payload = bufWkt.anyUnpack(message.payload, this.typeRegistry);
53
- invariant(payload, `Empty payload: ${payloadTypename}}`, {
54
- F: __dxlog_file,
55
- L: 48,
56
- S: this,
57
- A: [
58
- "payload",
59
- "`Empty payload: ${payloadTypename}}`"
60
- ]
61
- });
62
- return payload;
63
- }
64
- /**
65
- * Get the payload type.
66
- */
67
- getPayloadType(message) {
68
- if (!message.payload) {
69
- return void 0;
70
- }
71
- const [, type] = message.payload.typeUrl.split("/");
72
- return type;
73
- }
74
- /**
75
- * Create a packed message.
76
- */
77
- createMessage(type, { source, target, payload, serviceId }) {
78
- return buf.create(MessageSchema, {
79
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
80
- source,
81
- target,
82
- serviceId,
83
- payload: payload ? bufWkt.anyPack(type, buf.create(type, payload)) : void 0
84
- });
85
- }
86
- };
87
- var toUint8Array = async (data) => {
88
- if (data instanceof Buffer) {
89
- return bufferToArray(data);
90
- }
91
- if (data instanceof Blob) {
92
- return new Uint8Array(await data.arrayBuffer());
93
- }
94
- throw new Error(`Unexpected datatype: ${data}`);
95
- };
96
-
97
- // packages/core/mesh/edge-client/src/defs.ts
98
- import { bufWkt as bufWkt2 } from "@dxos/protocols/buf";
99
- import { SwarmRequestSchema, SwarmResponseSchema, TextMessageSchema } from "@dxos/protocols/buf/dxos/edge/messenger_pb";
100
- var protocol = new Protocol([
101
- SwarmRequestSchema,
102
- SwarmResponseSchema,
103
- TextMessageSchema,
104
- bufWkt2.AnySchema
105
- ]);
106
-
107
- export {
108
- getTypename,
109
- Protocol,
110
- toUint8Array,
111
- protocol
112
- };
113
- //# sourceMappingURL=chunk-ZWJXA37R.mjs.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/protocol.ts", "../../../src/defs.ts"],
4
- "sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport { invariant } from '@dxos/invariant';\nimport { buf, bufWkt } from '@dxos/protocols/buf';\nimport { type Message, MessageSchema, type PeerSchema } from '@dxos/protocols/buf/dxos/edge/messenger_pb';\nimport { bufferToArray } from '@dxos/util';\n\nexport type PeerData = buf.MessageInitShape<typeof PeerSchema>;\n\nexport const getTypename = (typeName: string) => `type.googleapis.com/${typeName}`;\n\n/**\n * NOTE: The type registry should be extended with all message types.\n */\nexport class Protocol {\n private readonly _typeRegistry: buf.Registry;\n\n constructor(types: buf.DescMessage[]) {\n this._typeRegistry = buf.createRegistry(...types);\n }\n\n get typeRegistry(): buf.Registry {\n return this._typeRegistry;\n }\n\n toJson(message: Message): any {\n try {\n return buf.toJson(MessageSchema, message, { registry: this.typeRegistry });\n } catch (err) {\n return { type: this.getPayloadType(message) };\n }\n }\n\n /**\n * Return the payload with the given type.\n */\n getPayload<Desc extends buf.DescMessage>(message: Message, type: Desc): buf.MessageShape<Desc> {\n invariant(message.payload);\n const payloadTypename = this.getPayloadType(message);\n if (type && type.typeName !== payloadTypename) {\n throw new Error(`Unexpected payload type: ${payloadTypename}; expected ${type.typeName}`);\n }\n\n invariant(bufWkt.anyIs(message.payload, type), `Unexpected payload type: ${payloadTypename}}`);\n const payload = bufWkt.anyUnpack(message.payload, this.typeRegistry) as buf.MessageShape<Desc>;\n invariant(payload, `Empty payload: ${payloadTypename}}`);\n return payload;\n }\n\n /**\n * Get the payload type.\n */\n getPayloadType(message: Message): string | undefined {\n if (!message.payload) {\n return undefined;\n }\n\n const [, type] = message.payload.typeUrl.split('/');\n return type;\n }\n\n /**\n * Create a packed message.\n */\n createMessage<Desc extends buf.DescMessage>(\n type: Desc,\n {\n source,\n target,\n payload,\n serviceId,\n }: {\n source?: PeerData;\n target?: PeerData[];\n payload?: buf.MessageInitShape<Desc>;\n serviceId?: string;\n },\n ) {\n return buf.create(MessageSchema, {\n timestamp: new Date().toISOString(),\n source,\n target,\n serviceId,\n payload: payload ? bufWkt.anyPack(type, buf.create(type, payload)) : undefined,\n });\n }\n}\n\n/**\n * Convert websocket data to Uint8Array.\n */\nexport const toUint8Array = async (data: any): Promise<Uint8Array> => {\n // Node.\n if (data instanceof Buffer) {\n return bufferToArray(data);\n }\n\n // Browser.\n if (data instanceof Blob) {\n return new Uint8Array(await (data as Blob).arrayBuffer());\n }\n\n throw new Error(`Unexpected datatype: ${data}`);\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { bufWkt } from '@dxos/protocols/buf';\nimport { SwarmRequestSchema, SwarmResponseSchema, TextMessageSchema } from '@dxos/protocols/buf/dxos/edge/messenger_pb';\n\nimport { Protocol } from './protocol';\n\nexport const protocol = new Protocol([SwarmRequestSchema, SwarmResponseSchema, TextMessageSchema, bufWkt.AnySchema]);\n"],
5
- "mappings": ";AAIA,SAASA,iBAAiB;AAC1B,SAASC,KAAKC,cAAc;AAC5B,SAAuBC,qBAAsC;AAC7D,SAASC,qBAAqB;;AAIvB,IAAMC,cAAc,CAACC,aAAqB,uBAAuBA,QAAAA;AAKjE,IAAMC,WAAN,MAAMA;EAGXC,YAAYC,OAA0B;AACpC,SAAKC,gBAAgBT,IAAIU,eAAc,GAAIF,KAAAA;EAC7C;EAEA,IAAIG,eAA6B;AAC/B,WAAO,KAAKF;EACd;EAEAG,OAAOC,SAAuB;AAC5B,QAAI;AACF,aAAOb,IAAIY,OAAOV,eAAeW,SAAS;QAAEC,UAAU,KAAKH;MAAa,CAAA;IAC1E,SAASI,KAAK;AACZ,aAAO;QAAEC,MAAM,KAAKC,eAAeJ,OAAAA;MAAS;IAC9C;EACF;;;;EAKAK,WAAyCL,SAAkBG,MAAoC;AAC7FjB,cAAUc,QAAQM,SAAO,QAAA;;;;;;;;;AACzB,UAAMC,kBAAkB,KAAKH,eAAeJ,OAAAA;AAC5C,QAAIG,QAAQA,KAAKX,aAAae,iBAAiB;AAC7C,YAAM,IAAIC,MAAM,4BAA4BD,eAAAA,cAA6BJ,KAAKX,QAAQ,EAAE;IAC1F;AAEAN,cAAUE,OAAOqB,MAAMT,QAAQM,SAASH,IAAAA,GAAO,4BAA4BI,eAAAA,KAAkB;;;;;;;;;AAC7F,UAAMD,UAAUlB,OAAOsB,UAAUV,QAAQM,SAAS,KAAKR,YAAY;AACnEZ,cAAUoB,SAAS,kBAAkBC,eAAAA,KAAkB;;;;;;;;;AACvD,WAAOD;EACT;;;;EAKAF,eAAeJ,SAAsC;AACnD,QAAI,CAACA,QAAQM,SAAS;AACpB,aAAOK;IACT;AAEA,UAAM,CAAA,EAAGR,IAAAA,IAAQH,QAAQM,QAAQM,QAAQC,MAAM,GAAA;AAC/C,WAAOV;EACT;;;;EAKAW,cACEX,MACA,EACEY,QACAC,QACAV,SACAW,UAAS,GAOX;AACA,WAAO9B,IAAI+B,OAAO7B,eAAe;MAC/B8B,YAAW,oBAAIC,KAAAA,GAAOC,YAAW;MACjCN;MACAC;MACAC;MACAX,SAASA,UAAUlB,OAAOkC,QAAQnB,MAAMhB,IAAI+B,OAAOf,MAAMG,OAAAA,CAAAA,IAAYK;IACvE,CAAA;EACF;AACF;AAKO,IAAMY,eAAe,OAAOC,SAAAA;AAEjC,MAAIA,gBAAgBC,QAAQ;AAC1B,WAAOnC,cAAckC,IAAAA;EACvB;AAGA,MAAIA,gBAAgBE,MAAM;AACxB,WAAO,IAAIC,WAAW,MAAOH,KAAcI,YAAW,CAAA;EACxD;AAEA,QAAM,IAAIpB,MAAM,wBAAwBgB,IAAAA,EAAM;AAChD;;;ACrGA,SAASK,UAAAA,eAAc;AACvB,SAASC,oBAAoBC,qBAAqBC,yBAAyB;AAIpE,IAAMC,WAAW,IAAIC,SAAS;EAACC;EAAoBC;EAAqBC;EAAmBC,QAAOC;CAAU;",
6
- "names": ["invariant", "buf", "bufWkt", "MessageSchema", "bufferToArray", "getTypename", "typeName", "Protocol", "constructor", "types", "_typeRegistry", "createRegistry", "typeRegistry", "toJson", "message", "registry", "err", "type", "getPayloadType", "getPayload", "payload", "payloadTypename", "Error", "anyIs", "anyUnpack", "undefined", "typeUrl", "split", "createMessage", "source", "target", "serviceId", "create", "timestamp", "Date", "toISOString", "anyPack", "toUint8Array", "data", "Buffer", "Blob", "Uint8Array", "arrayBuffer", "bufWkt", "SwarmRequestSchema", "SwarmResponseSchema", "TextMessageSchema", "protocol", "Protocol", "SwarmRequestSchema", "SwarmResponseSchema", "TextMessageSchema", "bufWkt", "AnySchema"]
7
- }
@@ -1,122 +0,0 @@
1
- import {
2
- protocol,
3
- toUint8Array
4
- } from "../chunk-ZWJXA37R.mjs";
5
-
6
- // packages/core/mesh/edge-client/src/testing/test-utils.ts
7
- import WebSocket from "isomorphic-ws";
8
- import { Trigger } from "@dxos/async";
9
- import { log } from "@dxos/log";
10
- import { buf } from "@dxos/protocols/buf";
11
- import { MessageSchema, TextMessageSchema } from "@dxos/protocols/buf/dxos/edge/messenger_pb";
12
- var __dxlog_file = "/home/runner/work/dxos/dxos/packages/core/mesh/edge-client/src/testing/test-utils.ts";
13
- var DEFAULT_PORT = 8080;
14
- var createTestEdgeWsServer = async (port = DEFAULT_PORT, params) => {
15
- const server = new WebSocket.Server({
16
- port,
17
- verifyClient: createConnectionDelayHandler(params)
18
- });
19
- let connection;
20
- const messageSink = [];
21
- const closeTrigger = new Trigger();
22
- const sendResponseMessage = createResponseSender(() => connection);
23
- server.on("connection", (ws) => {
24
- connection = ws;
25
- ws.on("error", (err) => log.catch(err, void 0, {
26
- F: __dxlog_file,
27
- L: 34,
28
- S: void 0,
29
- C: (f, a) => f(...a)
30
- }));
31
- ws.on("message", async (data) => {
32
- if (String(data) === "__ping__") {
33
- ws.send("__pong__");
34
- return;
35
- }
36
- const { request, requestPayload } = await decodeRequest(params, data);
37
- if (params?.messageHandler) {
38
- const responsePayload = await params.messageHandler(requestPayload);
39
- if (responsePayload && connection) {
40
- sendResponseMessage(request, responsePayload);
41
- }
42
- }
43
- log("message", {
44
- payload: requestPayload
45
- }, {
46
- F: __dxlog_file,
47
- L: 47,
48
- S: void 0,
49
- C: (f, a) => f(...a)
50
- });
51
- messageSink.push(requestPayload);
52
- });
53
- ws.on("close", () => {
54
- connection = void 0;
55
- closeTrigger.wake();
56
- });
57
- });
58
- return {
59
- server,
60
- messageSink,
61
- endpoint: `ws://localhost:${port}`,
62
- cleanup: () => server.close(),
63
- currentConnection: () => connection,
64
- sendResponseMessage,
65
- closeConnection: () => {
66
- closeTrigger.reset();
67
- connection.close(1011);
68
- return closeTrigger.wait();
69
- }
70
- };
71
- };
72
- var createConnectionDelayHandler = (params) => {
73
- return (_, callback) => {
74
- if (params?.admitConnection) {
75
- log("delaying edge connection admission", void 0, {
76
- F: __dxlog_file,
77
- L: 75,
78
- S: void 0,
79
- C: (f, a) => f(...a)
80
- });
81
- void params.admitConnection.wait().then(() => {
82
- callback(true);
83
- log("edge connection admitted", void 0, {
84
- F: __dxlog_file,
85
- L: 78,
86
- S: void 0,
87
- C: (f, a) => f(...a)
88
- });
89
- });
90
- } else {
91
- callback(true);
92
- }
93
- };
94
- };
95
- var createResponseSender = (connection) => {
96
- return (request, responsePayload) => {
97
- const recipient = request.source;
98
- connection().send(buf.toBinary(MessageSchema, buf.create(MessageSchema, {
99
- source: {
100
- identityKey: recipient.identityKey,
101
- peerKey: recipient.peerKey
102
- },
103
- serviceId: request.serviceId,
104
- payload: {
105
- value: responsePayload
106
- }
107
- })));
108
- };
109
- };
110
- var decodeRequest = async (params, data) => {
111
- const request = buf.fromBinary(MessageSchema, await toUint8Array(data));
112
- const requestPayload = params?.payloadDecoder ? params.payloadDecoder(request.payload.value) : protocol.getPayload(request, TextMessageSchema);
113
- return {
114
- request,
115
- requestPayload
116
- };
117
- };
118
- export {
119
- DEFAULT_PORT,
120
- createTestEdgeWsServer
121
- };
122
- //# sourceMappingURL=index.mjs.map