@dxos/teleport 0.1.17 → 0.1.19

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 (37) hide show
  1. package/dist/lib/browser/index.mjs +161 -20
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/browser/{testing.mjs → testing/index.mjs} +103 -23
  5. package/dist/lib/browser/testing/index.mjs.map +7 -0
  6. package/dist/lib/node/index.cjs +165 -21
  7. package/dist/lib/node/index.cjs.map +4 -4
  8. package/dist/lib/node/meta.json +1 -1
  9. package/dist/lib/node/{testing.cjs → testing/index.cjs} +106 -23
  10. package/dist/lib/node/testing/index.cjs.map +7 -0
  11. package/dist/types/src/index.d.ts +2 -0
  12. package/dist/types/src/index.d.ts.map +1 -1
  13. package/dist/types/src/muxing/framer.d.ts +2 -1
  14. package/dist/types/src/muxing/framer.d.ts.map +1 -1
  15. package/dist/types/src/rpc-extension.d.ts +17 -0
  16. package/dist/types/src/rpc-extension.d.ts.map +1 -0
  17. package/dist/types/src/testing/index.d.ts +3 -0
  18. package/dist/types/src/testing/index.d.ts.map +1 -0
  19. package/dist/types/src/{testing.d.ts → testing/test-builder.d.ts} +2 -2
  20. package/dist/types/src/testing/test-builder.d.ts.map +1 -0
  21. package/dist/types/src/testing/test-extension.d.ts +20 -0
  22. package/dist/types/src/testing/test-extension.d.ts.map +1 -0
  23. package/package.json +10 -10
  24. package/src/index.ts +2 -0
  25. package/src/muxing/framer.test.ts +9 -8
  26. package/src/muxing/framer.ts +11 -10
  27. package/src/rpc-extension.ts +63 -0
  28. package/src/teleport.test.ts +1 -1
  29. package/src/testing/index.ts +6 -0
  30. package/src/{testing.ts → testing/test-builder.ts} +1 -1
  31. package/src/{test-extension.ts → testing/test-extension.ts} +18 -5
  32. package/testing.js +1 -1
  33. package/dist/lib/browser/testing.mjs.map +0 -7
  34. package/dist/lib/node/testing.cjs.map +0 -7
  35. package/dist/types/src/test-extension.d.ts +0 -12
  36. package/dist/types/src/test-extension.d.ts.map +0 -1
  37. package/dist/types/src/testing.d.ts.map +0 -1
@@ -1,6 +1,6 @@
1
1
  import "@dxos/node-std/globals"
2
2
 
3
- // packages/core/mesh/teleport/src/testing.ts
3
+ // packages/core/mesh/teleport/src/testing/test-builder.ts
4
4
  import { pipeline } from "@dxos/node-std/stream";
5
5
  import { PublicKey as PublicKey2 } from "@dxos/keys";
6
6
  import { log as log3 } from "@dxos/log";
@@ -50,8 +50,7 @@ var Framer = class {
50
50
  });
51
51
  this.port = {
52
52
  send: (message) => {
53
- this._stream.push(encodeLength(message.length));
54
- this._stream.push(message);
53
+ this._stream.push(encodeFrame(message));
55
54
  },
56
55
  subscribe: (callback) => {
57
56
  var _a;
@@ -70,7 +69,7 @@ var Framer = class {
70
69
  _popFrames() {
71
70
  let offset = 0;
72
71
  while (offset < this._buffer.length) {
73
- const frame = readFrame(this._buffer, offset);
72
+ const frame = decodeFrame(this._buffer, offset);
74
73
  if (!frame) {
75
74
  break;
76
75
  }
@@ -87,7 +86,7 @@ var Framer = class {
87
86
  this._stream.destroy();
88
87
  }
89
88
  };
90
- var readFrame = (buffer, offset) => {
89
+ var decodeFrame = (buffer, offset) => {
91
90
  try {
92
91
  const frameLength = varint.decode(buffer, offset);
93
92
  const tagLength = varint.decode.bytes;
@@ -107,12 +106,12 @@ var readFrame = (buffer, offset) => {
107
106
  }
108
107
  }
109
108
  };
110
- var encodeLength = (length) => {
111
- const res = varint.encode(length, Buffer.allocUnsafe(4)).subarray(0, varint.encode.bytes);
112
- if (varint.encode.bytes > 4) {
113
- throw new Error("Frame too large");
114
- }
115
- return res;
109
+ var encodeFrame = (payload) => {
110
+ const tagLength = varint.encodingLength(payload.length);
111
+ const frame = Buffer.allocUnsafe(tagLength + payload.length);
112
+ varint.encode(payload.length, frame);
113
+ frame.set(payload, tagLength);
114
+ return frame;
116
115
  };
117
116
 
118
117
  // packages/core/mesh/teleport/src/muxing/muxer.ts
@@ -234,14 +233,14 @@ var Muxer = class {
234
233
  log("Received command", {
235
234
  cmd
236
235
  }, {
237
- file: "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/muxing/muxer.ts",
236
+ file: "muxer.ts",
238
237
  line: 194,
239
238
  scope: this,
240
239
  callSite: (f, a) => f(...a)
241
240
  });
242
241
  if (this._destroyed || this._destroying) {
243
242
  log.warn("Received command after destroy", {}, {
244
- file: "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/muxing/muxer.ts",
243
+ file: "muxer.ts",
245
244
  line: 197,
246
245
  scope: this,
247
246
  callSite: (f, a) => f(...a)
@@ -269,7 +268,7 @@ var Muxer = class {
269
268
  log.warn("Received data for channel before it was opened", {
270
269
  tag: stream.tag
271
270
  }, {
272
- file: "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/muxing/muxer.ts",
271
+ file: "muxer.ts",
273
272
  line: 221,
274
273
  scope: this,
275
274
  callSite: (f, a) => f(...a)
@@ -334,7 +333,7 @@ var Teleport = class {
334
333
  onError: (err) => {
335
334
  void this.destroy(err).catch(() => {
336
335
  log2.error("Error during destroy", err, {
337
- file: "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/teleport.ts",
336
+ file: "teleport.ts",
338
337
  line: 34,
339
338
  scope: this,
340
339
  callSite: (f, a) => f(...a)
@@ -361,7 +360,7 @@ var Teleport = class {
361
360
  log2("remote extension", {
362
361
  name
363
362
  }, {
364
- file: "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/teleport.ts",
363
+ file: "teleport.ts",
365
364
  line: 61,
366
365
  scope: this,
367
366
  callSite: (f, a) => f(...a)
@@ -406,7 +405,7 @@ var Teleport = class {
406
405
  await extension.onClose(err);
407
406
  } catch (err1) {
408
407
  log2.catch(err1, {}, {
409
- file: "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/teleport.ts",
408
+ file: "teleport.ts",
410
409
  line: 117,
411
410
  scope: this,
412
411
  callSite: (f, a) => f(...a)
@@ -422,7 +421,7 @@ var Teleport = class {
422
421
  log2("addExtension", {
423
422
  name
424
423
  }, {
425
- file: "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/teleport.ts",
424
+ file: "teleport.ts",
426
425
  line: 129,
427
426
  scope: this,
428
427
  callSite: (f, a) => f(...a)
@@ -454,7 +453,7 @@ var Teleport = class {
454
453
  log2("open extension", {
455
454
  extensionName
456
455
  }, {
457
- file: "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/teleport.ts",
456
+ file: "teleport.ts",
458
457
  line: 159,
459
458
  scope: this,
460
459
  callSite: (f, a) => f(...a)
@@ -482,7 +481,7 @@ var Teleport = class {
482
481
  log2("extension opened", {
483
482
  extensionName
484
483
  }, {
485
- file: "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/teleport.ts",
484
+ file: "teleport.ts",
486
485
  line: 182,
487
486
  scope: this,
488
487
  callSite: (f, a) => f(...a)
@@ -545,7 +544,7 @@ var ControlExtension = class {
545
544
  }
546
545
  };
547
546
 
548
- // packages/core/mesh/teleport/src/testing.ts
547
+ // packages/core/mesh/teleport/src/testing/test-builder.ts
549
548
  var TestBuilder = class {
550
549
  constructor() {
551
550
  this._peers = new Array();
@@ -603,7 +602,7 @@ var TestPeer = class {
603
602
  pipeline(this.teleport.stream, peer.teleport.stream, (err) => {
604
603
  if (err && err.code !== "ERR_STREAM_PREMATURE_CLOSE") {
605
604
  log3.catch(err, {}, {
606
- file: "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/testing.ts",
605
+ file: "test-builder.ts",
607
606
  line: 67,
608
607
  scope: this,
609
608
  callSite: (f, a) => f(...a)
@@ -616,8 +615,89 @@ var TestPeer = class {
616
615
  await ((_a = this.teleport) == null ? void 0 : _a.destroy());
617
616
  }
618
617
  };
618
+
619
+ // packages/core/mesh/teleport/src/testing/test-extension.ts
620
+ import assert4 from "@dxos/node-std/assert";
621
+ import { asyncTimeout as asyncTimeout2, Trigger } from "@dxos/async";
622
+ import { log as log4 } from "@dxos/log";
623
+ import { schema as schema3 } from "@dxos/protocols";
624
+ import { createProtoRpcPeer as createProtoRpcPeer2 } from "@dxos/rpc";
625
+ var TestExtension = class {
626
+ constructor(callbacks = {}) {
627
+ this.callbacks = callbacks;
628
+ this.open = new Trigger();
629
+ this.closed = new Trigger();
630
+ }
631
+ get remotePeerId() {
632
+ var _a;
633
+ return (_a = this.extensionContext) == null ? void 0 : _a.remotePeerId;
634
+ }
635
+ async onOpen(context) {
636
+ var _a, _b;
637
+ log4("onOpen", {
638
+ localPeerId: context.localPeerId,
639
+ remotePeerId: context.remotePeerId
640
+ }, {
641
+ file: "test-extension.ts",
642
+ line: 33,
643
+ scope: this,
644
+ callSite: (f, a) => f(...a)
645
+ });
646
+ this.extensionContext = context;
647
+ this._rpc = createProtoRpcPeer2({
648
+ port: context.createPort("rpc", {
649
+ contentType: 'application/x-protobuf; messageType="dxos.rpc.Message"'
650
+ }),
651
+ requested: {
652
+ TestService: schema3.getService("example.testing.rpc.TestService")
653
+ },
654
+ exposed: {
655
+ TestService: schema3.getService("example.testing.rpc.TestService")
656
+ },
657
+ handlers: {
658
+ TestService: {
659
+ voidCall: async (request) => {
660
+ },
661
+ testCall: async (request) => {
662
+ return {
663
+ data: request.data
664
+ };
665
+ }
666
+ }
667
+ },
668
+ timeout: 1e3
669
+ });
670
+ await this._rpc.open();
671
+ await ((_b = (_a = this.callbacks).onOpen) == null ? void 0 : _b.call(_a));
672
+ this.open.wake();
673
+ }
674
+ async onClose(err) {
675
+ var _a, _b, _c;
676
+ log4("onClose", {
677
+ err
678
+ }, {
679
+ file: "test-extension.ts",
680
+ line: 67,
681
+ scope: this,
682
+ callSite: (f, a) => f(...a)
683
+ });
684
+ await ((_b = (_a = this.callbacks).onClose) == null ? void 0 : _b.call(_a));
685
+ this.closed.wake();
686
+ await ((_c = this._rpc) == null ? void 0 : _c.close());
687
+ }
688
+ async test() {
689
+ await this.open.wait({
690
+ timeout: 500
691
+ });
692
+ const res = await asyncTimeout2(this._rpc.rpc.TestService.testCall({
693
+ data: "test"
694
+ }), 500);
695
+ assert4(res.data === "test");
696
+ }
697
+ };
619
698
  export {
620
699
  TestBuilder,
700
+ TestExtension,
621
701
  TestPeer
622
702
  };
623
- //# sourceMappingURL=testing.mjs.map
703
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/testing/test-builder.ts", "../../../../src/teleport.ts", "../../../../src/muxing/framer.ts", "../../../../src/muxing/muxer.ts", "../../../../src/testing/test-extension.ts"],
4
+ "sourcesContent": ["//\n// Copyright 2022 DXOS.org\n//\n\nimport { pipeline } from 'node:stream';\n\nimport { PublicKey } from '@dxos/keys';\nimport { log } from '@dxos/log';\n\nimport { Teleport } from '../teleport';\n\nexport class TestBuilder {\n private readonly _peers = new Array<TestPeer>();\n\n createPeer(peerId?: PublicKey): TestPeer {\n const peer = new TestPeer(peerId);\n this._peers.push(peer);\n return peer;\n }\n\n async destroy() {\n await Promise.all(this._peers.map((agent) => agent.destroy()));\n }\n\n /**\n * Simulates two peers connected via P2P network.\n */\n async createPipedPeers({ peerId1, peerId2 }: { peerId1?: PublicKey; peerId2?: PublicKey } = {}) {\n const peer1 = this.createPeer(peerId1);\n const peer2 = this.createPeer(peerId2);\n\n peer1.initializeTeleport({ initiator: true, remotePeerId: peer2.peerId });\n peer2.initializeTeleport({ initiator: false, remotePeerId: peer1.peerId });\n\n peer1.pipeline(peer2);\n peer2.pipeline(peer1);\n\n await Promise.all([peer1.teleport!.open(), peer2.teleport!.open()]);\n\n return { peer1, peer2 };\n }\n}\n\nexport class TestPeer {\n public teleport?: Teleport;\n\n constructor(public readonly peerId: PublicKey = PublicKey.random()) {}\n\n initializeTeleport({ initiator, remotePeerId }: { initiator: boolean; remotePeerId: PublicKey }) {\n if (this.teleport) {\n return this;\n }\n this.teleport = new Teleport({\n initiator,\n localPeerId: this.peerId,\n remotePeerId\n });\n return this;\n }\n\n pipeline(peer: TestPeer) {\n if (!this.teleport || !peer.teleport) {\n throw new Error('Teleport not initialized');\n }\n pipeline(this.teleport.stream, peer.teleport.stream, (err) => {\n if (err && err.code !== 'ERR_STREAM_PREMATURE_CLOSE') {\n log.catch(err);\n }\n });\n }\n\n async destroy() {\n await this.teleport?.destroy();\n }\n}\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport assert from 'node:assert';\nimport { Duplex } from 'node:stream';\n\nimport { asyncTimeout, scheduleTaskInterval, runInContextAsync, synchronized, scheduleTask } from '@dxos/async';\nimport { Context } from '@dxos/context';\nimport { failUndefined } from '@dxos/debug';\nimport { PublicKey } from '@dxos/keys';\nimport { log } from '@dxos/log';\nimport { schema } from '@dxos/protocols';\nimport { ControlService } from '@dxos/protocols/proto/dxos/mesh/teleport/control';\nimport { createProtoRpcPeer, ProtoRpcPeer, RpcClosedError } from '@dxos/rpc';\nimport { Callback } from '@dxos/util';\n\nimport { CreateChannelOpts, Muxer, RpcPort } from './muxing';\n\nexport type TeleportParams = {\n initiator: boolean;\n localPeerId: PublicKey;\n remotePeerId: PublicKey;\n};\n\nexport class Teleport {\n public readonly initiator: boolean;\n public readonly localPeerId: PublicKey;\n public readonly remotePeerId: PublicKey;\n\n private readonly _ctx = new Context({\n onError: (err) => {\n void this.destroy(err).catch(() => {\n log.error('Error during destroy', err);\n });\n }\n });\n\n private readonly _muxer = new Muxer();\n\n private readonly _control = new ControlExtension({\n heartbeatInterval: 3000,\n heartbeatTimeout: 3000\n });\n\n private readonly _extensions = new Map<string, TeleportExtension>();\n private readonly _remoteExtensions = new Set<string>();\n\n private _open = false;\n\n constructor({ initiator, localPeerId, remotePeerId }: TeleportParams) {\n assert(typeof initiator === 'boolean');\n assert(PublicKey.isPublicKey(localPeerId));\n assert(PublicKey.isPublicKey(remotePeerId));\n assert(typeof initiator === 'boolean');\n this.initiator = initiator;\n this.localPeerId = localPeerId;\n this.remotePeerId = remotePeerId;\n\n this._control.onExtensionRegistered.set(async (name) => {\n log('remote extension', { name });\n assert(!this._remoteExtensions.has(name), 'Remote extension already exists');\n this._remoteExtensions.add(name);\n\n if (this._extensions.has(name)) {\n try {\n await this._openExtension(name);\n } catch (err: any) {\n await this.destroy(err);\n }\n }\n });\n\n {\n // Destroy Teleport when the stream is closed.\n this._muxer.stream.on('close', async () => {\n await this.destroy();\n });\n\n this._muxer.stream.on('error', async (err) => {\n await this.destroy(err);\n });\n }\n }\n\n get stream(): Duplex {\n return this._muxer.stream;\n }\n\n /**\n * Blocks until the handshake is complete.\n */\n async open() {\n this._setExtension('dxos.mesh.teleport.control', this._control);\n await this._openExtension('dxos.mesh.teleport.control');\n this._open = true;\n }\n\n async close(err?: Error) {\n // TODO(dmaretskyi): Try soft close.\n\n await this.destroy(err);\n }\n\n @synchronized\n async destroy(err?: Error) {\n if (this._ctx.disposed) {\n return;\n }\n\n await this._ctx.dispose();\n\n for (const extension of this._extensions.values()) {\n try {\n await extension.onClose(err);\n } catch (err: any) {\n log.catch(err);\n }\n }\n\n this._muxer.destroy(err);\n }\n\n addExtension(name: string, extension: TeleportExtension) {\n if (!this._open) {\n throw new Error('Not open');\n }\n\n log('addExtension', { name });\n this._setExtension(name, extension);\n\n // Perform the registration in a separate tick as this might block while the remote side is opening the extension.\n scheduleTask(this._ctx, async () => {\n try {\n await this._control.registerExtension(name);\n } catch (err) {\n if (err instanceof RpcClosedError) {\n return;\n }\n throw err;\n }\n });\n\n if (this._remoteExtensions.has(name)) {\n // Open the extension in a separate tick.\n scheduleTask(this._ctx, async () => {\n await this._openExtension(name);\n });\n }\n }\n\n private _setExtension(extensionName: string, extension: TeleportExtension) {\n assert(!extensionName.includes('/'), 'Invalid extension name');\n assert(!this._extensions.has(extensionName), 'Extension already exists');\n this._extensions.set(extensionName, extension);\n }\n\n private async _openExtension(extensionName: string) {\n log('open extension', { extensionName });\n const extension = this._extensions.get(extensionName) ?? failUndefined();\n\n const context: ExtensionContext = {\n initiator: this.initiator,\n localPeerId: this.localPeerId,\n remotePeerId: this.remotePeerId,\n createPort: (channelName: string, opts?: CreateChannelOpts) => {\n assert(!channelName.includes('/'), 'Invalid channel name');\n return this._muxer.createPort(`${extensionName}/${channelName}`, opts);\n },\n createStream: (channelName: string, opts?: CreateChannelOpts) => {\n assert(!channelName.includes('/'), 'Invalid channel name');\n return this._muxer.createStream(`${extensionName}/${channelName}`, opts);\n },\n close: (err) => {\n void runInContextAsync(this._ctx, async () => {\n await this.close(err);\n });\n }\n };\n\n await extension.onOpen(context);\n log('extension opened', { extensionName });\n }\n}\n\nexport type ExtensionContext = {\n /**\n * One of the peers will be designated an initiator.\n */\n initiator: boolean;\n localPeerId: PublicKey;\n remotePeerId: PublicKey;\n createStream(tag: string, opts?: CreateChannelOpts): Duplex;\n createPort(tag: string, opts?: CreateChannelOpts): RpcPort;\n close(err?: Error): void;\n};\n\nexport interface TeleportExtension {\n onOpen(context: ExtensionContext): Promise<void>;\n onClose(err?: Error): Promise<void>;\n}\n\ntype ControlExtensionOpts = {\n heartbeatInterval: number;\n heartbeatTimeout: number;\n};\n\nclass ControlExtension implements TeleportExtension {\n private readonly _ctx = new Context({\n onError: (err) => {\n this._extensionContext.close(err);\n }\n });\n\n private _extensionContext!: ExtensionContext;\n private _rpc!: ProtoRpcPeer<{ Control: ControlService }>;\n\n public readonly onExtensionRegistered = new Callback<(extensionName: string) => void>();\n public readonly onTimeout = new Callback<() => void>();\n\n constructor(private readonly opts: ControlExtensionOpts) {}\n\n async onOpen(extensionContext: ExtensionContext): Promise<void> {\n this._extensionContext = extensionContext;\n\n // NOTE: Make sure that RPC timeout is greater than the heartbeat timeout.\n // TODO(dmaretskyi): Allow overwriting the timeout on individual RPC calls?\n this._rpc = createProtoRpcPeer<ControlRpcBundle, ControlRpcBundle>({\n requested: {\n Control: schema.getService('dxos.mesh.teleport.control.ControlService')\n },\n exposed: {\n Control: schema.getService('dxos.mesh.teleport.control.ControlService')\n },\n handlers: {\n Control: {\n registerExtension: async (request) => {\n this.onExtensionRegistered.call(request.name);\n },\n heartbeat: async (request) => {\n // Ok.\n }\n }\n },\n port: extensionContext.createPort('rpc', {\n contentType: 'application/x-protobuf; messageType=\"dxos.rpc.Message\"'\n })\n });\n\n await this._rpc.open();\n\n scheduleTaskInterval(\n this._ctx,\n async () => {\n try {\n await asyncTimeout(this._rpc.rpc.Control.heartbeat(), this.opts.heartbeatTimeout);\n } catch (err: any) {\n this.onTimeout.call();\n }\n },\n this.opts.heartbeatInterval\n );\n }\n\n async onClose(err?: Error): Promise<void> {\n await this._ctx.dispose();\n await this._rpc.close();\n }\n\n async registerExtension(name: string) {\n await this._rpc.rpc.Control.registerExtension({ name });\n }\n}\n\ntype ControlRpcBundle = {\n Control: ControlService;\n};\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport assert from 'node:assert';\nimport { Duplex } from 'node:stream';\nimport * as varint from 'varint';\n\nimport { RpcPort } from './rpc-port';\n\n/**\n * Framer that turns a stream of binary messages into a framed RpcPort.\n *\n * Buffers are written prefixed by their length encoded as a varint.\n */\nexport class Framer {\n // private readonly _tagBuffer = Buffer.alloc(4)\n private _messageCb?: (msg: Uint8Array) => void;\n private _subscribeCb?: () => void;\n private _buffer?: Buffer; // The rest of the bytes from the previous write call.\n\n private readonly _stream = new Duplex({\n objectMode: false,\n read: () => {},\n write: (chunk, encoding, callback) => {\n assert(!this._subscribeCb, 'Internal Framer bug. Concurrent writes detected.');\n\n if (this._buffer && this._buffer.length > 0) {\n this._buffer = Buffer.concat([this._buffer, chunk]);\n } else {\n this._buffer = chunk;\n }\n\n if (this._messageCb) {\n this._popFrames();\n callback();\n } else {\n this._subscribeCb = () => {\n // Schedule the processing of the chunk after the peer subscribes to the messages.\n this._popFrames();\n this._subscribeCb = undefined;\n callback();\n };\n }\n }\n });\n\n public readonly port: RpcPort = {\n send: (message) => {\n // log('write', { len: message.length, frame: Buffer.from(message).toString('hex') })\n this._stream.push(encodeFrame(message));\n },\n subscribe: (callback) => {\n assert(!this._messageCb, 'Rpc port already has a message listener.');\n this._messageCb = callback;\n this._subscribeCb?.();\n return () => {\n this._messageCb = undefined;\n };\n }\n };\n\n get stream(): Duplex {\n return this._stream;\n }\n\n /**\n * Attempts to pop frames from the buffer and call the message callback.\n */\n private _popFrames() {\n let offset = 0;\n while (offset < this._buffer!.length) {\n const frame = decodeFrame(this._buffer!, offset);\n\n if (!frame) {\n break; // Couldn't read frame but there are still bytes left in the buffer.\n }\n offset += frame.bytesConsumed;\n // TODO(dmaretskyi): Possible bug if the peer unsubscribes while we're reading frames.\n // log('read', { len: frame.payload.length, frame: Buffer.from(frame.payload).toString('hex') })\n this._messageCb!(frame.payload);\n }\n\n if (offset < this._buffer!.length) {\n // Save the rest of the bytes for the next write call.\n this._buffer = this._buffer!.subarray(offset);\n } else {\n this._buffer = undefined;\n }\n }\n\n destroy() {\n // TODO(dmaretskyi): Call stream.end() instead?\n this._stream.destroy();\n }\n}\n\n/**\n * Attempts to read a frame from the input buffer.\n */\nexport const decodeFrame = (buffer: Buffer, offset: number): { payload: Buffer; bytesConsumed: number } | undefined => {\n try {\n const frameLength = varint.decode(buffer, offset);\n const tagLength = varint.decode.bytes;\n\n if (buffer.length < offset + tagLength + frameLength) {\n // Not enough bytes to read the frame.\n return undefined;\n }\n\n const payload = buffer.subarray(offset + tagLength, offset + tagLength + frameLength);\n\n return {\n payload,\n bytesConsumed: tagLength + frameLength\n };\n } catch (err) {\n if (err instanceof RangeError) {\n // Not enough bytes to read the tag.\n return undefined;\n } else {\n throw err;\n }\n }\n};\n\nexport const encodeFrame = (payload: Uint8Array): Buffer => {\n const tagLength = varint.encodingLength(payload.length);\n const frame = Buffer.allocUnsafe(tagLength + payload.length);\n varint.encode(payload.length, frame);\n frame.set(payload, tagLength);\n return frame;\n};\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport assert from 'node:assert';\nimport { Duplex } from 'node:stream';\n\nimport { Event } from '@dxos/async';\nimport { failUndefined } from '@dxos/debug';\nimport { log } from '@dxos/log';\nimport { schema } from '@dxos/protocols';\nimport { Command } from '@dxos/protocols/proto/dxos/mesh/muxer';\n\nimport { Framer } from './framer';\nimport { RpcPort } from './rpc-port';\n\nconst codec = schema.getCodecForType('dxos.mesh.muxer.Command');\n\nexport type CleanupCb = void | (() => void);\n\nexport type CreateChannelOpts = {\n /**\n * MIME type of the wire content.\n *\n * Examples:\n * - application/octet-stream\n * - application/x-protobuf; messageType=\"dxos.rpc.Message\"\n */\n contentType?: string;\n};\n\n/**\n * Channel based multiplexer.\n *\n * Can be used to open a number of channels represented by streams or RPC ports.\n * Performs framing for RPC ports.\n * Will buffer data until the remote peer opens the channel.\n *\n * The API will not advertise channels that as they are opened by the remote peer.\n * A higher level API (could be build on top of this muxer) for channel discovery is required.\n */\nexport class Muxer {\n private readonly _framer = new Framer();\n public readonly stream = this._framer.stream;\n\n private readonly _channelsByLocalId = new Map<number, Channel>();\n private readonly _channelsByTag = new Map<string, Channel>();\n\n private _nextId = 0;\n private _destroyed = false;\n private _destroying = false;\n\n public close = new Event<Error | undefined>();\n\n constructor() {\n this._framer.port.subscribe((msg) => {\n this._handleCommand(codec.decode(msg));\n });\n }\n\n /**\n * Creates a duplex Node.js-style stream.\n * The remote peer is expected to call `createStream` with the same tag.\n * The stream is immediately readable and writable.\n * NOTE: The data will be buffered until the stream is opened remotely with the same tag (may cause a memory leak).\n */\n createStream(tag: string, opts: CreateChannelOpts = {}): Duplex {\n const channel = this._getOrCreateStream({\n tag,\n contentType: opts.contentType\n });\n assert(!channel.push, `Channel already open: ${tag}`);\n\n const stream = new Duplex({\n write: (data, encoding, callback) => {\n this._sendData(channel, data);\n // TODO(dmaretskyi): Should we error if sending data has errored?\n callback();\n },\n read: () => {} // No-op. We will push data when we receive it.\n });\n\n channel.push = (data) => {\n stream.push(data);\n };\n channel.destroy = (err) => {\n // TODO(dmaretskyi): Call stream.end() instead?\n stream.destroy(err);\n };\n\n // NOTE: Make sure channel.push is set before sending the command.\n this._sendCommand({\n openChannel: {\n id: channel.id,\n tag: channel.tag,\n contentType: channel.contentType\n }\n });\n\n return stream;\n }\n\n /**\n * Creates an RPC port.\n * The remote peer is expected to call `createPort` with the same tag.\n * The port is immediately usable.\n * NOTE: The data will be buffered until the stream is opened remotely with the same tag (may cause a memory leak).\n */\n createPort(tag: string, opts: CreateChannelOpts = {}): RpcPort {\n const channel = this._getOrCreateStream({\n tag,\n contentType: opts.contentType\n });\n assert(!channel.push, `Channel already open: ${tag}`);\n\n // We need to buffer incoming data until the port is subscribed to.\n let inboundBuffer: Uint8Array[] = [];\n let callback: ((data: Uint8Array) => void) | undefined;\n\n channel.push = (data) => {\n if (callback) {\n callback(data);\n } else {\n inboundBuffer.push(data);\n }\n };\n\n const port: RpcPort = {\n send: (data: Uint8Array) => {\n this._sendData(channel, data); // TODO(dmaretskyi): Error propagation?\n\n // TODO(dmaretskyi): Debugging.\n // appendFileSync('log.json', JSON.stringify(schema.getCodecForType('dxos.rpc.RpcMessage').decode(data), null, 2) + '\\n')\n },\n subscribe: (cb: (data: Uint8Array) => void) => {\n assert(!callback, 'Only one subscriber is allowed');\n callback = cb;\n for (const data of inboundBuffer) {\n cb(data);\n }\n inboundBuffer = [];\n }\n };\n\n // NOTE: Make sure channel.push is set before sending the command.\n this._sendCommand({\n openChannel: {\n id: channel.id,\n tag: channel.tag,\n contentType: channel.contentType\n }\n });\n\n return port;\n }\n\n /**\n * Force-close with optional error.\n */\n destroy(err?: Error) {\n if (this._destroying) {\n return;\n }\n this._destroying = true;\n\n this._sendCommand({\n destroy: {\n error: err?.message\n }\n });\n this._dispose();\n }\n\n private _dispose(err?: Error) {\n if (this._destroyed) {\n return;\n }\n\n this._destroyed = true;\n this._framer.destroy();\n\n for (const channel of this._channelsByTag.values()) {\n channel.destroy?.(err);\n }\n\n this.close.emit(err);\n\n // Make it easy for GC.\n this._channelsByLocalId.clear();\n this._channelsByTag.clear();\n }\n\n private _handleCommand(cmd: Command) {\n log('Received command', { cmd });\n\n if (this._destroyed || this._destroying) {\n log.warn('Received command after destroy');\n return;\n }\n\n if (cmd.openChannel) {\n const channel = this._getOrCreateStream({\n tag: cmd.openChannel.tag,\n contentType: cmd.openChannel.contentType\n });\n channel.remoteId = cmd.openChannel.id;\n\n // Flush any buffered data.\n for (const data of channel.buffer) {\n this._sendCommand({\n data: {\n channelId: channel.remoteId,\n data\n }\n });\n }\n channel.buffer = [];\n } else if (cmd.data) {\n const stream = this._channelsByLocalId.get(cmd.data.channelId) ?? failUndefined();\n if (!stream.push) {\n log.warn('Received data for channel before it was opened', { tag: stream.tag });\n return;\n }\n stream.push(cmd.data.data);\n } else if (cmd.destroy) {\n this._dispose();\n }\n }\n\n private _sendCommand(cmd: Command) {\n Promise.resolve(this._framer.port.send(codec.encode(cmd))).catch((err) => {\n this.destroy(err);\n });\n }\n\n private _getOrCreateStream(params: CreateChannelInternalParams): Channel {\n let channel = this._channelsByTag.get(params.tag);\n if (!channel) {\n channel = {\n id: this._nextId++,\n remoteId: null,\n tag: params.tag,\n contentType: params.contentType,\n buffer: [],\n push: null,\n destroy: null\n };\n this._channelsByTag.set(channel.tag, channel);\n this._channelsByLocalId.set(channel.id, channel);\n }\n return channel;\n }\n\n private _sendData(channel: Channel, data: Uint8Array) {\n if (channel.remoteId === null) {\n // Remote side has not opened the channel yet.\n channel.buffer.push(data);\n } else {\n this._sendCommand({\n data: {\n channelId: channel.remoteId,\n data\n }\n });\n }\n }\n}\n\ntype Channel = {\n /**\n * Our local channel ID.\n * Incoming Data commands will have this ID.\n */\n id: number;\n tag: string;\n\n /**\n * Remote id is set when we receive an OpenChannel command.\n * The originating Data commands should carry this id.\n */\n remoteId: null | number;\n\n contentType?: string;\n\n /**\n * Send buffer.\n */\n buffer: Uint8Array[];\n\n /**\n * Set when we initialize a NodeJS stream or an RPC port consuming the channel.\n */\n push: null | ((data: Uint8Array) => void);\n\n destroy: null | ((err?: Error) => void);\n};\n\ntype CreateChannelInternalParams = {\n tag: string;\n contentType?: string;\n};\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport assert from 'node:assert';\n\nimport { asyncTimeout, Trigger } from '@dxos/async';\nimport { log } from '@dxos/log';\nimport { schema } from '@dxos/protocols';\nimport { TestService } from '@dxos/protocols/proto/example/testing/rpc';\nimport { createProtoRpcPeer, ProtoRpcPeer } from '@dxos/rpc';\n\nimport { ExtensionContext, TeleportExtension } from '../teleport';\n\ninterface TestExtensionCallbacks {\n onOpen?: () => Promise<void>;\n onClose?: () => Promise<void>;\n}\n\nexport class TestExtension implements TeleportExtension {\n public readonly open = new Trigger();\n public readonly closed = new Trigger();\n public extensionContext: ExtensionContext | undefined;\n private _rpc!: ProtoRpcPeer<{ TestService: TestService }>;\n\n constructor(public readonly callbacks: TestExtensionCallbacks = {}) {}\n\n get remotePeerId() {\n return this.extensionContext?.remotePeerId;\n }\n\n async onOpen(context: ExtensionContext) {\n log('onOpen', { localPeerId: context.localPeerId, remotePeerId: context.remotePeerId });\n this.extensionContext = context;\n this._rpc = createProtoRpcPeer<{ TestService: TestService }, { TestService: TestService }>({\n port: context.createPort('rpc', {\n contentType: 'application/x-protobuf; messageType=\"dxos.rpc.Message\"'\n }),\n requested: {\n TestService: schema.getService('example.testing.rpc.TestService')\n },\n exposed: {\n TestService: schema.getService('example.testing.rpc.TestService')\n },\n handlers: {\n TestService: {\n voidCall: async (request) => {\n // Ok.\n },\n testCall: async (request) => {\n return {\n data: request.data\n };\n }\n }\n },\n timeout: 1000\n });\n\n await this._rpc.open();\n await this.callbacks.onOpen?.();\n\n this.open.wake();\n }\n\n async onClose(err?: Error) {\n log('onClose', { err });\n await this.callbacks.onClose?.();\n this.closed.wake();\n await this._rpc?.close();\n }\n\n async test() {\n await this.open.wait({ timeout: 500 });\n const res = await asyncTimeout(this._rpc.rpc.TestService.testCall({ data: 'test' }), 500);\n assert(res.data === 'test');\n }\n}\n"],
5
+ "mappings": ";;;AAIA,SAASA,gBAAgB;AAEzB,SAASC,aAAAA,kBAAiB;AAC1B,SAASC,OAAAA,YAAW;;;ACHpB,OAAOC,aAAY;AAGnB,SAASC,cAAcC,sBAAsBC,mBAAmBC,cAAcC,oBAAoB;AAClG,SAASC,eAAe;AACxB,SAASC,iBAAAA,sBAAqB;AAC9B,SAASC,iBAAiB;AAC1B,SAASC,OAAAA,YAAW;AACpB,SAASC,UAAAA,eAAc;AAEvB,SAASC,oBAAkCC,sBAAsB;AACjE,SAASC,gBAAgB;;;ACXzB,OAAOC,YAAY;AACnB,SAASC,cAAc;AACvB,YAAYC,YAAY;AASjB,IAAMC,SAAN,MAAMA;EAAN;AAMYC,mBAAU,IAAIH,OAAO;MACpCI,YAAY;MACZC,MAAM,MAAM;MAAC;MACbC,OAAO,CAACC,OAAOC,UAAUC,aAAa;AACpCV,eAAO,CAAC,KAAKW,cAAc,kDAAA;AAE3B,YAAI,KAAKC,WAAW,KAAKA,QAAQC,SAAS,GAAG;AAC3C,eAAKD,UAAUE,OAAOC,OAAO;YAAC,KAAKH;YAASJ;WAAM;QACpD,OAAO;AACL,eAAKI,UAAUJ;QACjB;AAEA,YAAI,KAAKQ,YAAY;AACnB,eAAKC,WAAU;AACfP,mBAAAA;QACF,OAAO;AACL,eAAKC,eAAe,MAAM;AAExB,iBAAKM,WAAU;AACf,iBAAKN,eAAeO;AACpBR,qBAAAA;UACF;QACF;MACF;IACF,CAAA;AAEgBS,gBAAgB;MAC9BC,MAAM,CAACC,YAAY;AAEjB,aAAKjB,QAAQkB,KAAKC,YAAYF,OAAAA,CAAAA;MAChC;MACAG,WAAW,CAACd,aAAa;AApD7B;AAqDMV,eAAO,CAAC,KAAKgB,YAAY,0CAAA;AACzB,aAAKA,aAAaN;AAClB,mBAAKC,iBAAL;AACA,eAAO,MAAM;AACX,eAAKK,aAAaE;QACpB;MACF;IACF;;EAEA,IAAIO,SAAiB;AACnB,WAAO,KAAKrB;EACd;EAKQa,aAAa;AACnB,QAAIS,SAAS;AACb,WAAOA,SAAS,KAAKd,QAASC,QAAQ;AACpC,YAAMc,QAAQC,YAAY,KAAKhB,SAAUc,MAAAA;AAEzC,UAAI,CAACC,OAAO;AACV;MACF;AACAD,gBAAUC,MAAME;AAGhB,WAAKb,WAAYW,MAAMG,OAAO;IAChC;AAEA,QAAIJ,SAAS,KAAKd,QAASC,QAAQ;AAEjC,WAAKD,UAAU,KAAKA,QAASmB,SAASL,MAAAA;IACxC,OAAO;AACL,WAAKd,UAAUM;IACjB;EACF;EAEAc,UAAU;AAER,SAAK5B,QAAQ4B,QAAO;EACtB;AACF;AAKO,IAAMJ,cAAc,CAACK,QAAgBP,WAA2E;AACrH,MAAI;AACF,UAAMQ,cAAqBC,cAAOF,QAAQP,MAAAA;AAC1C,UAAMU,YAAmBD,cAAOE;AAEhC,QAAIJ,OAAOpB,SAASa,SAASU,YAAYF,aAAa;AAEpD,aAAOhB;IACT;AAEA,UAAMY,UAAUG,OAAOF,SAASL,SAASU,WAAWV,SAASU,YAAYF,WAAAA;AAEzE,WAAO;MACLJ;MACAD,eAAeO,YAAYF;IAC7B;EACF,SAASI,KAAP;AACA,QAAIA,eAAeC,YAAY;AAE7B,aAAOrB;IACT,OAAO;AACL,YAAMoB;IACR;EACF;AACF;AAEO,IAAMf,cAAc,CAACO,YAAgC;AAC1D,QAAMM,YAAmBI,sBAAeV,QAAQjB,MAAM;AACtD,QAAMc,QAAQb,OAAO2B,YAAYL,YAAYN,QAAQjB,MAAM;AAC3DX,EAAOwC,cAAOZ,QAAQjB,QAAQc,KAAAA;AAC9BA,QAAMgB,IAAIb,SAASM,SAAAA;AACnB,SAAOT;AACT;;;AChIA,OAAOiB,aAAY;AACnB,SAASC,UAAAA,eAAc;AAEvB,SAASC,aAAa;AACtB,SAASC,qBAAqB;AAC9B,SAASC,WAAW;AACpB,SAASC,cAAc;AAMvB,IAAMC,QAAQC,OAAOC,gBAAgB,yBAAA;AAyB9B,IAAMC,QAAN,MAAMA;EAaXC,cAAc;AAZGC,mBAAU,IAAIC,OAAAA;AACfC,kBAAS,KAAKF,QAAQE;AAErBC,8BAAqB,oBAAIC,IAAAA;AACzBC,0BAAiB,oBAAID,IAAAA;AAE9BE,mBAAU;AACVC,sBAAa;AACbC,uBAAc;AAEfC,iBAAQ,IAAIC,MAAAA;AAGjB,SAAKV,QAAQW,KAAKC,UAAU,CAACC,QAAQ;AACnC,WAAKC,eAAenB,MAAMoB,OAAOF,GAAAA,CAAAA;IACnC,CAAA;EACF;EAQAG,aAAaC,KAAaC,OAA0B,CAAC,GAAW;AAC9D,UAAMC,UAAU,KAAKC,mBAAmB;MACtCH;MACAI,aAAaH,KAAKG;IACpB,CAAA;AACAC,IAAAA,QAAO,CAACH,QAAQI,MAAM,yBAAyBN,KAAK;AAEpD,UAAMf,SAAS,IAAIsB,QAAO;MACxBC,OAAO,CAACC,MAAMC,UAAUC,aAAa;AACnC,aAAKC,UAAUV,SAASO,IAAAA;AAExBE,iBAAAA;MACF;MACAE,MAAM,MAAM;MAAC;IACf,CAAA;AAEAX,YAAQI,OAAO,CAACG,SAAS;AACvBxB,aAAOqB,KAAKG,IAAAA;IACd;AACAP,YAAQY,UAAU,CAACC,QAAQ;AAEzB9B,aAAO6B,QAAQC,GAAAA;IACjB;AAGA,SAAKC,aAAa;MAChBC,aAAa;QACXC,IAAIhB,QAAQgB;QACZlB,KAAKE,QAAQF;QACbI,aAAaF,QAAQE;MACvB;IACF,CAAA;AAEA,WAAOnB;EACT;EAQAkC,WAAWnB,KAAaC,OAA0B,CAAC,GAAY;AAC7D,UAAMC,UAAU,KAAKC,mBAAmB;MACtCH;MACAI,aAAaH,KAAKG;IACpB,CAAA;AACAC,IAAAA,QAAO,CAACH,QAAQI,MAAM,yBAAyBN,KAAK;AAGpD,QAAIoB,gBAA8B,CAAA;AAClC,QAAIT;AAEJT,YAAQI,OAAO,CAACG,SAAS;AACvB,UAAIE,UAAU;AACZA,iBAASF,IAAAA;MACX,OAAO;AACLW,sBAAcd,KAAKG,IAAAA;MACrB;IACF;AAEA,UAAMf,OAAgB;MACpB2B,MAAM,CAACZ,SAAqB;AAC1B,aAAKG,UAAUV,SAASO,IAAAA;MAI1B;MACAd,WAAW,CAAC2B,OAAmC;AAC7CjB,QAAAA,QAAO,CAACM,UAAU,gCAAA;AAClBA,mBAAWW;AACX,mBAAWb,QAAQW,eAAe;AAChCE,aAAGb,IAAAA;QACL;AACAW,wBAAgB,CAAA;MAClB;IACF;AAGA,SAAKJ,aAAa;MAChBC,aAAa;QACXC,IAAIhB,QAAQgB;QACZlB,KAAKE,QAAQF;QACbI,aAAaF,QAAQE;MACvB;IACF,CAAA;AAEA,WAAOV;EACT;EAKAoB,QAAQC,KAAa;AACnB,QAAI,KAAKxB,aAAa;AACpB;IACF;AACA,SAAKA,cAAc;AAEnB,SAAKyB,aAAa;MAChBF,SAAS;QACPS,OAAOR,2BAAKS;MACd;IACF,CAAA;AACA,SAAKC,SAAQ;EACf;EAEQA,SAASV,KAAa;AA7KhC;AA8KI,QAAI,KAAKzB,YAAY;AACnB;IACF;AAEA,SAAKA,aAAa;AAClB,SAAKP,QAAQ+B,QAAO;AAEpB,eAAWZ,WAAW,KAAKd,eAAesC,OAAM,GAAI;AAClDxB,oBAAQY,YAARZ,iCAAkBa;IACpB;AAEA,SAAKvB,MAAMmC,KAAKZ,GAAAA;AAGhB,SAAK7B,mBAAmB0C,MAAK;AAC7B,SAAKxC,eAAewC,MAAK;EAC3B;EAEQ/B,eAAegC,KAAc;AAhMvC;AAiMIC,QAAI,oBAAoB;MAAED;IAAI,GAAA;;;;;;AAE9B,QAAI,KAAKvC,cAAc,KAAKC,aAAa;AACvCuC,UAAIC,KAAK,kCAAA,CAAA,GAAA;;;;;;AACT;IACF;AAEA,QAAIF,IAAIZ,aAAa;AACnB,YAAMf,UAAU,KAAKC,mBAAmB;QACtCH,KAAK6B,IAAIZ,YAAYjB;QACrBI,aAAayB,IAAIZ,YAAYb;MAC/B,CAAA;AACAF,cAAQ8B,WAAWH,IAAIZ,YAAYC;AAGnC,iBAAWT,QAAQP,QAAQ+B,QAAQ;AACjC,aAAKjB,aAAa;UAChBP,MAAM;YACJyB,WAAWhC,QAAQ8B;YACnBvB;UACF;QACF,CAAA;MACF;AACAP,cAAQ+B,SAAS,CAAA;IACnB,WAAWJ,IAAIpB,MAAM;AACnB,YAAMxB,UAAS,UAAKC,mBAAmBiD,IAAIN,IAAIpB,KAAKyB,SAAS,MAA9C,YAAmDE,cAAAA;AAClE,UAAI,CAACnD,OAAOqB,MAAM;AAChBwB,YAAIC,KAAK,kDAAkD;UAAE/B,KAAKf,OAAOe;QAAI,GAAA;;;;;;AAC7E;MACF;AACAf,aAAOqB,KAAKuB,IAAIpB,KAAKA,IAAI;IAC3B,WAAWoB,IAAIf,SAAS;AACtB,WAAKW,SAAQ;IACf;EACF;EAEQT,aAAaa,KAAc;AACjCQ,YAAQC,QAAQ,KAAKvD,QAAQW,KAAK2B,KAAK3C,MAAM6D,OAAOV,GAAAA,CAAAA,CAAAA,EAAOW,MAAM,CAACzB,QAAQ;AACxE,WAAKD,QAAQC,GAAAA;IACf,CAAA;EACF;EAEQZ,mBAAmBsC,QAA8C;AACvE,QAAIvC,UAAU,KAAKd,eAAe+C,IAAIM,OAAOzC,GAAG;AAChD,QAAI,CAACE,SAAS;AACZA,gBAAU;QACRgB,IAAI,KAAK7B;QACT2C,UAAU;QACVhC,KAAKyC,OAAOzC;QACZI,aAAaqC,OAAOrC;QACpB6B,QAAQ,CAAA;QACR3B,MAAM;QACNQ,SAAS;MACX;AACA,WAAK1B,eAAesD,IAAIxC,QAAQF,KAAKE,OAAAA;AACrC,WAAKhB,mBAAmBwD,IAAIxC,QAAQgB,IAAIhB,OAAAA;IAC1C;AACA,WAAOA;EACT;EAEQU,UAAUV,SAAkBO,MAAkB;AACpD,QAAIP,QAAQ8B,aAAa,MAAM;AAE7B9B,cAAQ+B,OAAO3B,KAAKG,IAAAA;IACtB,OAAO;AACL,WAAKO,aAAa;QAChBP,MAAM;UACJyB,WAAWhC,QAAQ8B;UACnBvB;QACF;MACF,CAAA;IACF;EACF;AACF;;;AFtQA,IAAA,aAAA,SAAA,YAAA,QAAA,KAAA,MAAA;;;;;;;;;;AAqBO,IAAMkC,WAAN,MAAMA;EAyBXC,YAAY,EAAEC,WAAWC,aAAaC,aAAY,GAAoB;AApBrDC,gBAAO,IAAIC,QAAQ;MAClCC,SAAS,CAACC,QAAQ;AAChB,aAAK,KAAKC,QAAQD,GAAAA,EAAKE,MAAM,MAAM;AACjCC,UAAAA,KAAIC,MAAM,wBAAwBJ,KAAAA;;;;;;QACpC,CAAA;MACF;IACF,CAAA;AAEiBK,kBAAS,IAAIC,MAAAA;AAEbC,oBAAW,IAAIC,iBAAiB;MAC/CC,mBAAmB;MACnBC,kBAAkB;IACpB,CAAA;AAEiBC,uBAAc,oBAAIC,IAAAA;AAClBC,6BAAoB,oBAAIC,IAAAA;AAEjCC,iBAAQ;AAGdC,IAAAA,QAAO,OAAOtB,cAAc,SAAA;AAC5BsB,IAAAA,QAAOC,UAAUC,YAAYvB,WAAAA,CAAAA;AAC7BqB,IAAAA,QAAOC,UAAUC,YAAYtB,YAAAA,CAAAA;AAC7BoB,IAAAA,QAAO,OAAOtB,cAAc,SAAA;AAC5B,SAAKA,YAAYA;AACjB,SAAKC,cAAcA;AACnB,SAAKC,eAAeA;AAEpB,SAAKW,SAASY,sBAAsBC,IAAI,OAAOC,SAAS;AACtDlB,MAAAA,KAAI,oBAAoB;QAAEkB;MAAK,GAAA;;;;;;AAC/BL,MAAAA,QAAO,CAAC,KAAKH,kBAAkBS,IAAID,IAAAA,GAAO,iCAAA;AAC1C,WAAKR,kBAAkBU,IAAIF,IAAAA;AAE3B,UAAI,KAAKV,YAAYW,IAAID,IAAAA,GAAO;AAC9B,YAAI;AACF,gBAAM,KAAKG,eAAeH,IAAAA;QAC5B,SAASrB,KAAP;AACA,gBAAM,KAAKC,QAAQD,GAAAA;QACrB;MACF;IACF,CAAA;AAEA;AAEE,WAAKK,OAAOoB,OAAOC,GAAG,SAAS,YAAY;AACzC,cAAM,KAAKzB,QAAO;MACpB,CAAA;AAEA,WAAKI,OAAOoB,OAAOC,GAAG,SAAS,OAAO1B,QAAQ;AAC5C,cAAM,KAAKC,QAAQD,GAAAA;MACrB,CAAA;IACF;EACF;EAEA,IAAIyB,SAAiB;AACnB,WAAO,KAAKpB,OAAOoB;EACrB;EAKA,MAAME,OAAO;AACX,SAAKC,cAAc,8BAA8B,KAAKrB,QAAQ;AAC9D,UAAM,KAAKiB,eAAe,4BAAA;AAC1B,SAAKT,QAAQ;EACf;EAEA,MAAMc,MAAM7B,KAAa;AAGvB,UAAM,KAAKC,QAAQD,GAAAA;EACrB;EAEA,MACMC,QAAQD,KAAa;AACzB,QAAI,KAAKH,KAAKiC,UAAU;AACtB;IACF;AAEA,UAAM,KAAKjC,KAAKkC,QAAO;AAEvB,eAAWC,aAAa,KAAKrB,YAAYsB,OAAM,GAAI;AACjD,UAAI;AACF,cAAMD,UAAUE,QAAQlC,GAAAA;MAC1B,SAASA,MAAP;AACAG,QAAAA,KAAID,MAAMF,MAAAA,CAAAA,GAAAA;;;;;;MACZ;IACF;AAEA,SAAKK,OAAOJ,QAAQD,GAAAA;EACtB;EAEAmC,aAAad,MAAcW,WAA8B;AACvD,QAAI,CAAC,KAAKjB,OAAO;AACf,YAAM,IAAIqB,MAAM,UAAA;IAClB;AAEAjC,IAAAA,KAAI,gBAAgB;MAAEkB;IAAK,GAAA;;;;;;AAC3B,SAAKO,cAAcP,MAAMW,SAAAA;AAGzBK,iBAAa,KAAKxC,MAAM,YAAY;AAClC,UAAI;AACF,cAAM,KAAKU,SAAS+B,kBAAkBjB,IAAAA;MACxC,SAASrB,KAAP;AACA,YAAIA,eAAeuC,gBAAgB;AACjC;QACF;AACA,cAAMvC;MACR;IACF,CAAA;AAEA,QAAI,KAAKa,kBAAkBS,IAAID,IAAAA,GAAO;AAEpCgB,mBAAa,KAAKxC,MAAM,YAAY;AAClC,cAAM,KAAK2B,eAAeH,IAAAA;MAC5B,CAAA;IACF;EACF;EAEQO,cAAcY,eAAuBR,WAA8B;AACzEhB,IAAAA,QAAO,CAACwB,cAAcC,SAAS,GAAA,GAAM,wBAAA;AACrCzB,IAAAA,QAAO,CAAC,KAAKL,YAAYW,IAAIkB,aAAAA,GAAgB,0BAAA;AAC7C,SAAK7B,YAAYS,IAAIoB,eAAeR,SAAAA;EACtC;EAEA,MAAcR,eAAegB,eAAuB;AA7JtD;AA8JIrC,IAAAA,KAAI,kBAAkB;MAAEqC;IAAc,GAAA;;;;;;AACtC,UAAMR,aAAY,UAAKrB,YAAY+B,IAAIF,aAAAA,MAArB,YAAuCG,eAAAA;AAEzD,UAAMC,UAA4B;MAChClD,WAAW,KAAKA;MAChBC,aAAa,KAAKA;MAClBC,cAAc,KAAKA;MACnBiD,YAAY,CAACC,aAAqBC,SAA6B;AAC7D/B,QAAAA,QAAO,CAAC8B,YAAYL,SAAS,GAAA,GAAM,sBAAA;AACnC,eAAO,KAAKpC,OAAOwC,WAAW,GAAGL,iBAAiBM,eAAeC,IAAAA;MACnE;MACAC,cAAc,CAACF,aAAqBC,SAA6B;AAC/D/B,QAAAA,QAAO,CAAC8B,YAAYL,SAAS,GAAA,GAAM,sBAAA;AACnC,eAAO,KAAKpC,OAAO2C,aAAa,GAAGR,iBAAiBM,eAAeC,IAAAA;MACrE;MACAlB,OAAO,CAAC7B,QAAQ;AACd,aAAKiD,kBAAkB,KAAKpD,MAAM,YAAY;AAC5C,gBAAM,KAAKgC,MAAM7B,GAAAA;QACnB,CAAA;MACF;IACF;AAEA,UAAMgC,UAAUkB,OAAON,OAAAA;AACvBzC,IAAAA,KAAI,oBAAoB;MAAEqC;IAAc,GAAA;;;;;;EAC1C;AACF;;EA/EGW;GA/EU3D,SAAAA,WAAAA,WAAAA,IAAAA;AAsLb,IAAMgB,mBAAN,MAAMA;EAaJf,YAA6BsD,MAA4B;gBAA5BA;SAZZlD,OAAO,IAAIC,QAAQ;MAClCC,SAAS,CAACC,QAAQ;AAChB,aAAKoD,kBAAkBvB,MAAM7B,GAAAA;MAC/B;IACF,CAAA;SAKgBmB,wBAAwB,IAAIkC,SAAAA;SAC5BC,YAAY,IAAID,SAAAA;EAE0B;EAE1D,MAAMH,OAAOK,kBAAmD;AAC9D,SAAKH,oBAAoBG;AAIzB,SAAKC,OAAOC,mBAAuD;MACjEC,WAAW;QACTC,SAASC,QAAOC,WAAW,2CAAA;MAC7B;MACAC,SAAS;QACPH,SAASC,QAAOC,WAAW,2CAAA;MAC7B;MACAE,UAAU;QACRJ,SAAS;UACPrB,mBAAmB,OAAO0B,YAAY;AACpC,iBAAK7C,sBAAsB8C,KAAKD,QAAQ3C,IAAI;UAC9C;UACA6C,WAAW,OAAOF,YAAY;UAE9B;QACF;MACF;MACAG,MAAMZ,iBAAiBV,WAAW,OAAO;QACvCuB,aAAa;MACf,CAAA;IACF,CAAA;AAEA,UAAM,KAAKZ,KAAK7B,KAAI;AAEpB0C,yBACE,KAAKxE,MACL,YAAY;AACV,UAAI;AACF,cAAMyE,aAAa,KAAKd,KAAKe,IAAIZ,QAAQO,UAAS,GAAI,KAAKnB,KAAKrC,gBAAgB;MAClF,SAASV,KAAP;AACA,aAAKsD,UAAUW,KAAI;MACrB;IACF,GACA,KAAKlB,KAAKtC,iBAAiB;EAE/B;EAEA,MAAMyB,QAAQlC,KAA4B;AACxC,UAAM,KAAKH,KAAKkC,QAAO;AACvB,UAAM,KAAKyB,KAAK3B,MAAK;EACvB;EAEA,MAAMS,kBAAkBjB,MAAc;AACpC,UAAM,KAAKmC,KAAKe,IAAIZ,QAAQrB,kBAAkB;MAAEjB;IAAK,CAAA;EACvD;AACF;;;ADrQO,IAAMmD,cAAN,MAAMA;EAAN;AACYC,kBAAS,IAAIC,MAAAA;;EAE9BC,WAAWC,QAA8B;AACvC,UAAMC,OAAO,IAAIC,SAASF,MAAAA;AAC1B,SAAKH,OAAOM,KAAKF,IAAAA;AACjB,WAAOA;EACT;EAEA,MAAMG,UAAU;AACd,UAAMC,QAAQC,IAAI,KAAKT,OAAOU,IAAI,CAACC,UAAUA,MAAMJ,QAAO,CAAA,CAAA;EAC5D;EAKA,MAAMK,iBAAiB,EAAEC,SAASC,QAAO,IAAmD,CAAC,GAAG;AAC9F,UAAMC,QAAQ,KAAKb,WAAWW,OAAAA;AAC9B,UAAMG,QAAQ,KAAKd,WAAWY,OAAAA;AAE9BC,UAAME,mBAAmB;MAAEC,WAAW;MAAMC,cAAcH,MAAMb;IAAO,CAAA;AACvEa,UAAMC,mBAAmB;MAAEC,WAAW;MAAOC,cAAcJ,MAAMZ;IAAO,CAAA;AAExEY,UAAMK,SAASJ,KAAAA;AACfA,UAAMI,SAASL,KAAAA;AAEf,UAAMP,QAAQC,IAAI;MAACM,MAAMM,SAAUC,KAAI;MAAIN,MAAMK,SAAUC,KAAI;KAAG;AAElE,WAAO;MAAEP;MAAOC;IAAM;EACxB;AACF;AAEO,IAAMX,WAAN,MAAMA;EAGXkB,YAA4BpB,SAAoBqB,WAAUC,OAAM,GAAI;kBAAxCtB;EAAyC;EAErEc,mBAAmB,EAAEC,WAAWC,aAAY,GAAqD;AAC/F,QAAI,KAAKE,UAAU;AACjB,aAAO;IACT;AACA,SAAKA,WAAW,IAAIK,SAAS;MAC3BR;MACAS,aAAa,KAAKxB;MAClBgB;IACF,CAAA;AACA,WAAO;EACT;EAEAC,SAAShB,MAAgB;AACvB,QAAI,CAAC,KAAKiB,YAAY,CAACjB,KAAKiB,UAAU;AACpC,YAAM,IAAIO,MAAM,0BAAA;IAClB;AACAR,aAAS,KAAKC,SAASQ,QAAQzB,KAAKiB,SAASQ,QAAQ,CAACC,QAAQ;AAC5D,UAAIA,OAAOA,IAAIC,SAAS,8BAA8B;AACpDC,QAAAA,KAAIC,MAAMH,KAAAA,CAAAA,GAAAA;;;;;;MACZ;IACF,CAAA;EACF;EAEA,MAAMvB,UAAU;AAvElB;AAwEI,YAAM,UAAKc,aAAL,mBAAed;EACvB;AACF;;;AItEA,OAAO2B,aAAY;AAEnB,SAASC,gBAAAA,eAAcC,eAAe;AACtC,SAASC,OAAAA,YAAW;AACpB,SAASC,UAAAA,eAAc;AAEvB,SAASC,sBAAAA,2BAAwC;AAS1C,IAAMC,gBAAN,MAAMA;EAMXC,YAA4BC,YAAoC,CAAC,GAAG;qBAAxCA;SALZC,OAAO,IAAIP,QAAAA;SACXQ,SAAS,IAAIR,QAAAA;EAIwC;EAErE,IAAIS,eAAe;AA3BrB;AA4BI,YAAO,UAAKC,qBAAL,mBAAuBD;EAChC;EAEA,MAAME,OAAOC,SAA2B;AA/B1C;AAgCIX,IAAAA,KAAI,UAAU;MAAEY,aAAaD,QAAQC;MAAaJ,cAAcG,QAAQH;IAAa,GAAA;;;;;;AACrF,SAAKC,mBAAmBE;AACxB,SAAKE,OAAOX,oBAA+E;MACzFY,MAAMH,QAAQI,WAAW,OAAO;QAC9BC,aAAa;MACf,CAAA;MACAC,WAAW;QACTC,aAAajB,QAAOkB,WAAW,iCAAA;MACjC;MACAC,SAAS;QACPF,aAAajB,QAAOkB,WAAW,iCAAA;MACjC;MACAE,UAAU;QACRH,aAAa;UACXI,UAAU,OAAOC,YAAY;UAE7B;UACAC,UAAU,OAAOD,YAAY;AAC3B,mBAAO;cACLE,MAAMF,QAAQE;YAChB;UACF;QACF;MACF;MACAC,SAAS;IACX,CAAA;AAEA,UAAM,KAAKb,KAAKP,KAAI;AACpB,YAAM,gBAAKD,WAAUK,WAAf;AAEN,SAAKJ,KAAKqB,KAAI;EAChB;EAEA,MAAMC,QAAQC,KAAa;AAjE7B;AAkEI7B,IAAAA,KAAI,WAAW;MAAE6B;IAAI,GAAA;;;;;;AACrB,YAAM,gBAAKxB,WAAUuB,YAAf;AACN,SAAKrB,OAAOoB,KAAI;AAChB,YAAM,UAAKd,SAAL,mBAAWiB;EACnB;EAEA,MAAMC,OAAO;AACX,UAAM,KAAKzB,KAAK0B,KAAK;MAAEN,SAAS;IAAI,CAAA;AACpC,UAAMO,MAAM,MAAMnC,cAAa,KAAKe,KAAKqB,IAAIhB,YAAYM,SAAS;MAAEC,MAAM;IAAO,CAAA,GAAI,GAAA;AACrF5B,IAAAA,QAAOoC,IAAIR,SAAS,MAAA;EACtB;AACF;",
6
+ "names": ["pipeline", "PublicKey", "log", "assert", "asyncTimeout", "scheduleTaskInterval", "runInContextAsync", "synchronized", "scheduleTask", "Context", "failUndefined", "PublicKey", "log", "schema", "createProtoRpcPeer", "RpcClosedError", "Callback", "assert", "Duplex", "varint", "Framer", "_stream", "objectMode", "read", "write", "chunk", "encoding", "callback", "_subscribeCb", "_buffer", "length", "Buffer", "concat", "_messageCb", "_popFrames", "undefined", "port", "send", "message", "push", "encodeFrame", "subscribe", "stream", "offset", "frame", "decodeFrame", "bytesConsumed", "payload", "subarray", "destroy", "buffer", "frameLength", "decode", "tagLength", "bytes", "err", "RangeError", "encodingLength", "allocUnsafe", "encode", "set", "assert", "Duplex", "Event", "failUndefined", "log", "schema", "codec", "schema", "getCodecForType", "Muxer", "constructor", "_framer", "Framer", "stream", "_channelsByLocalId", "Map", "_channelsByTag", "_nextId", "_destroyed", "_destroying", "close", "Event", "port", "subscribe", "msg", "_handleCommand", "decode", "createStream", "tag", "opts", "channel", "_getOrCreateStream", "contentType", "assert", "push", "Duplex", "write", "data", "encoding", "callback", "_sendData", "read", "destroy", "err", "_sendCommand", "openChannel", "id", "createPort", "inboundBuffer", "send", "cb", "error", "message", "_dispose", "values", "emit", "clear", "cmd", "log", "warn", "remoteId", "buffer", "channelId", "get", "failUndefined", "Promise", "resolve", "encode", "catch", "params", "set", "Teleport", "constructor", "initiator", "localPeerId", "remotePeerId", "_ctx", "Context", "onError", "err", "destroy", "catch", "log", "error", "_muxer", "Muxer", "_control", "ControlExtension", "heartbeatInterval", "heartbeatTimeout", "_extensions", "Map", "_remoteExtensions", "Set", "_open", "assert", "PublicKey", "isPublicKey", "onExtensionRegistered", "set", "name", "has", "add", "_openExtension", "stream", "on", "open", "_setExtension", "close", "disposed", "dispose", "extension", "values", "onClose", "addExtension", "Error", "scheduleTask", "registerExtension", "RpcClosedError", "extensionName", "includes", "get", "failUndefined", "context", "createPort", "channelName", "opts", "createStream", "runInContextAsync", "onOpen", "synchronized", "_extensionContext", "Callback", "onTimeout", "extensionContext", "_rpc", "createProtoRpcPeer", "requested", "Control", "schema", "getService", "exposed", "handlers", "request", "call", "heartbeat", "port", "contentType", "scheduleTaskInterval", "asyncTimeout", "rpc", "TestBuilder", "_peers", "Array", "createPeer", "peerId", "peer", "TestPeer", "push", "destroy", "Promise", "all", "map", "agent", "createPipedPeers", "peerId1", "peerId2", "peer1", "peer2", "initializeTeleport", "initiator", "remotePeerId", "pipeline", "teleport", "open", "constructor", "PublicKey", "random", "Teleport", "localPeerId", "Error", "stream", "err", "code", "log", "catch", "assert", "asyncTimeout", "Trigger", "log", "schema", "createProtoRpcPeer", "TestExtension", "constructor", "callbacks", "open", "closed", "remotePeerId", "extensionContext", "onOpen", "context", "localPeerId", "_rpc", "port", "createPort", "contentType", "requested", "TestService", "getService", "exposed", "handlers", "voidCall", "request", "testCall", "data", "timeout", "wake", "onClose", "err", "close", "test", "wait", "res", "rpc"]
7
+ }
@@ -28,8 +28,11 @@ var src_exports = {};
28
28
  __export(src_exports, {
29
29
  Framer: () => Framer,
30
30
  Muxer: () => Muxer,
31
+ RpcExtension: () => RpcExtension,
31
32
  Teleport: () => Teleport,
32
- readFrame: () => readFrame
33
+ TestExtension: () => TestExtension,
34
+ decodeFrame: () => decodeFrame,
35
+ encodeFrame: () => encodeFrame
33
36
  });
34
37
  module.exports = __toCommonJS(src_exports);
35
38
 
@@ -67,8 +70,7 @@ var Framer = class {
67
70
  });
68
71
  this.port = {
69
72
  send: (message) => {
70
- this._stream.push(encodeLength(message.length));
71
- this._stream.push(message);
73
+ this._stream.push(encodeFrame(message));
72
74
  },
73
75
  subscribe: (callback) => {
74
76
  var _a;
@@ -87,7 +89,7 @@ var Framer = class {
87
89
  _popFrames() {
88
90
  let offset = 0;
89
91
  while (offset < this._buffer.length) {
90
- const frame = readFrame(this._buffer, offset);
92
+ const frame = decodeFrame(this._buffer, offset);
91
93
  if (!frame) {
92
94
  break;
93
95
  }
@@ -104,7 +106,7 @@ var Framer = class {
104
106
  this._stream.destroy();
105
107
  }
106
108
  };
107
- var readFrame = (buffer, offset) => {
109
+ var decodeFrame = (buffer, offset) => {
108
110
  try {
109
111
  const frameLength = varint.decode(buffer, offset);
110
112
  const tagLength = varint.decode.bytes;
@@ -124,12 +126,12 @@ var readFrame = (buffer, offset) => {
124
126
  }
125
127
  }
126
128
  };
127
- var encodeLength = (length) => {
128
- const res = varint.encode(length, Buffer.allocUnsafe(4)).subarray(0, varint.encode.bytes);
129
- if (varint.encode.bytes > 4) {
130
- throw new Error("Frame too large");
131
- }
132
- return res;
129
+ var encodeFrame = (payload) => {
130
+ const tagLength = varint.encodingLength(payload.length);
131
+ const frame = Buffer.allocUnsafe(tagLength + payload.length);
132
+ varint.encode(payload.length, frame);
133
+ frame.set(payload, tagLength);
134
+ return frame;
133
135
  };
134
136
 
135
137
  // packages/core/mesh/teleport/src/muxing/muxer.ts
@@ -251,14 +253,14 @@ var Muxer = class {
251
253
  (0, import_log.log)("Received command", {
252
254
  cmd
253
255
  }, {
254
- file: "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/muxing/muxer.ts",
256
+ file: "muxer.ts",
255
257
  line: 194,
256
258
  scope: this,
257
259
  callSite: (f, a) => f(...a)
258
260
  });
259
261
  if (this._destroyed || this._destroying) {
260
262
  import_log.log.warn("Received command after destroy", {}, {
261
- file: "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/muxing/muxer.ts",
263
+ file: "muxer.ts",
262
264
  line: 197,
263
265
  scope: this,
264
266
  callSite: (f, a) => f(...a)
@@ -286,7 +288,7 @@ var Muxer = class {
286
288
  import_log.log.warn("Received data for channel before it was opened", {
287
289
  tag: stream.tag
288
290
  }, {
289
- file: "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/muxing/muxer.ts",
291
+ file: "muxer.ts",
290
292
  line: 221,
291
293
  scope: this,
292
294
  callSite: (f, a) => f(...a)
@@ -360,7 +362,7 @@ var Teleport = class {
360
362
  onError: (err) => {
361
363
  void this.destroy(err).catch(() => {
362
364
  import_log2.log.error("Error during destroy", err, {
363
- file: "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/teleport.ts",
365
+ file: "teleport.ts",
364
366
  line: 34,
365
367
  scope: this,
366
368
  callSite: (f, a) => f(...a)
@@ -387,7 +389,7 @@ var Teleport = class {
387
389
  (0, import_log2.log)("remote extension", {
388
390
  name
389
391
  }, {
390
- file: "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/teleport.ts",
392
+ file: "teleport.ts",
391
393
  line: 61,
392
394
  scope: this,
393
395
  callSite: (f, a) => f(...a)
@@ -432,7 +434,7 @@ var Teleport = class {
432
434
  await extension.onClose(err);
433
435
  } catch (err1) {
434
436
  import_log2.log.catch(err1, {}, {
435
- file: "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/teleport.ts",
437
+ file: "teleport.ts",
436
438
  line: 117,
437
439
  scope: this,
438
440
  callSite: (f, a) => f(...a)
@@ -448,7 +450,7 @@ var Teleport = class {
448
450
  (0, import_log2.log)("addExtension", {
449
451
  name
450
452
  }, {
451
- file: "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/teleport.ts",
453
+ file: "teleport.ts",
452
454
  line: 129,
453
455
  scope: this,
454
456
  callSite: (f, a) => f(...a)
@@ -480,7 +482,7 @@ var Teleport = class {
480
482
  (0, import_log2.log)("open extension", {
481
483
  extensionName
482
484
  }, {
483
- file: "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/teleport.ts",
485
+ file: "teleport.ts",
484
486
  line: 159,
485
487
  scope: this,
486
488
  callSite: (f, a) => f(...a)
@@ -508,7 +510,7 @@ var Teleport = class {
508
510
  (0, import_log2.log)("extension opened", {
509
511
  extensionName
510
512
  }, {
511
- file: "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/teleport.ts",
513
+ file: "teleport.ts",
512
514
  line: 182,
513
515
  scope: this,
514
516
  callSite: (f, a) => f(...a)
@@ -570,11 +572,153 @@ var ControlExtension = class {
570
572
  });
571
573
  }
572
574
  };
575
+
576
+ // packages/core/mesh/teleport/src/testing/test-extension.ts
577
+ var import_node_assert4 = __toESM(require("node:assert"));
578
+ var import_async3 = require("@dxos/async");
579
+ var import_log3 = require("@dxos/log");
580
+ var import_protocols3 = require("@dxos/protocols");
581
+ var import_rpc2 = require("@dxos/rpc");
582
+ var TestExtension = class {
583
+ constructor(callbacks = {}) {
584
+ this.callbacks = callbacks;
585
+ this.open = new import_async3.Trigger();
586
+ this.closed = new import_async3.Trigger();
587
+ }
588
+ get remotePeerId() {
589
+ var _a;
590
+ return (_a = this.extensionContext) == null ? void 0 : _a.remotePeerId;
591
+ }
592
+ async onOpen(context) {
593
+ var _a, _b;
594
+ (0, import_log3.log)("onOpen", {
595
+ localPeerId: context.localPeerId,
596
+ remotePeerId: context.remotePeerId
597
+ }, {
598
+ file: "test-extension.ts",
599
+ line: 33,
600
+ scope: this,
601
+ callSite: (f, a) => f(...a)
602
+ });
603
+ this.extensionContext = context;
604
+ this._rpc = (0, import_rpc2.createProtoRpcPeer)({
605
+ port: context.createPort("rpc", {
606
+ contentType: 'application/x-protobuf; messageType="dxos.rpc.Message"'
607
+ }),
608
+ requested: {
609
+ TestService: import_protocols3.schema.getService("example.testing.rpc.TestService")
610
+ },
611
+ exposed: {
612
+ TestService: import_protocols3.schema.getService("example.testing.rpc.TestService")
613
+ },
614
+ handlers: {
615
+ TestService: {
616
+ voidCall: async (request) => {
617
+ },
618
+ testCall: async (request) => {
619
+ return {
620
+ data: request.data
621
+ };
622
+ }
623
+ }
624
+ },
625
+ timeout: 1e3
626
+ });
627
+ await this._rpc.open();
628
+ await ((_b = (_a = this.callbacks).onOpen) == null ? void 0 : _b.call(_a));
629
+ this.open.wake();
630
+ }
631
+ async onClose(err) {
632
+ var _a, _b, _c;
633
+ (0, import_log3.log)("onClose", {
634
+ err
635
+ }, {
636
+ file: "test-extension.ts",
637
+ line: 67,
638
+ scope: this,
639
+ callSite: (f, a) => f(...a)
640
+ });
641
+ await ((_b = (_a = this.callbacks).onClose) == null ? void 0 : _b.call(_a));
642
+ this.closed.wake();
643
+ await ((_c = this._rpc) == null ? void 0 : _c.close());
644
+ }
645
+ async test() {
646
+ await this.open.wait({
647
+ timeout: 500
648
+ });
649
+ const res = await (0, import_async3.asyncTimeout)(this._rpc.rpc.TestService.testCall({
650
+ data: "test"
651
+ }), 500);
652
+ (0, import_node_assert4.default)(res.data === "test");
653
+ }
654
+ };
655
+
656
+ // packages/core/mesh/teleport/src/rpc-extension.ts
657
+ var import_node_assert5 = __toESM(require("node:assert"));
658
+ var import_async4 = require("@dxos/async");
659
+ var import_rpc3 = require("@dxos/rpc");
660
+ var __decorate2 = function(decorators, target, key, desc) {
661
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
662
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
663
+ r = Reflect.decorate(decorators, target, key, desc);
664
+ else
665
+ for (var i = decorators.length - 1; i >= 0; i--)
666
+ if (d = decorators[i])
667
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
668
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
669
+ };
670
+ var RpcExtension = class {
671
+ constructor(_params) {
672
+ this._params = _params;
673
+ }
674
+ get initiator() {
675
+ return this._extensionContext.initiator;
676
+ }
677
+ get localPeerId() {
678
+ return this._extensionContext.localPeerId;
679
+ }
680
+ get remotePeerId() {
681
+ return this._extensionContext.remotePeerId;
682
+ }
683
+ get rpc() {
684
+ (0, import_node_assert5.default)(this._rpc);
685
+ return this._rpc.rpc;
686
+ }
687
+ async onOpen(context) {
688
+ this._extensionContext = context;
689
+ const handlers = await this.getHandlers();
690
+ const port = context.createPort("rpc", {
691
+ contentType: 'application/x-protobuf; messageType="dxos.rpc.Message"'
692
+ });
693
+ this._rpc = (0, import_rpc3.createProtoRpcPeer)({
694
+ ...this._params,
695
+ handlers,
696
+ port
697
+ });
698
+ await this._rpc.open();
699
+ }
700
+ async onClose(err) {
701
+ var _a;
702
+ await ((_a = this._rpc) == null ? void 0 : _a.close());
703
+ }
704
+ close() {
705
+ this._extensionContext.close();
706
+ }
707
+ };
708
+ __decorate2([
709
+ import_async4.synchronized
710
+ ], RpcExtension.prototype, "onOpen", null);
711
+ __decorate2([
712
+ import_async4.synchronized
713
+ ], RpcExtension.prototype, "onClose", null);
573
714
  // Annotate the CommonJS export names for ESM import in node:
574
715
  0 && (module.exports = {
575
716
  Framer,
576
717
  Muxer,
718
+ RpcExtension,
577
719
  Teleport,
578
- readFrame
720
+ TestExtension,
721
+ decodeFrame,
722
+ encodeFrame
579
723
  });
580
724
  //# sourceMappingURL=index.cjs.map