@4players/odin-plugin-web 1.0.0-alpha.2 → 1.0.0-alpha.20

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 (95) hide show
  1. package/lib/common/msgpack.d.ts +2 -0
  2. package/lib/common/msgpack.js +117 -0
  3. package/{backend/lib → lib/plugin}/config.d.ts +5 -4
  4. package/lib/plugin/config.js +22 -0
  5. package/{backend/lib → lib/plugin}/connectionPool.d.ts +3 -3
  6. package/{backend/lib → lib/plugin}/connectionPool.js +32 -13
  7. package/lib/plugin/deviceManager.d.ts +12 -0
  8. package/lib/plugin/deviceManager.js +120 -0
  9. package/lib/plugin/h3/mainConnection.d.ts +31 -0
  10. package/lib/plugin/h3/mainConnection.js +195 -0
  11. package/{backend/lib → lib/plugin}/index.d.ts +30 -13
  12. package/lib/plugin/index.js +404 -0
  13. package/lib/plugin/mainConnection.d.ts +30 -0
  14. package/lib/plugin/mainConnection.js +21 -0
  15. package/{backend/lib/audioController.d.ts → lib/plugin/mediaController.d.ts} +12 -48
  16. package/lib/plugin/mediaController.js +215 -0
  17. package/lib/plugin/medias/audio-capture.d.ts +30 -0
  18. package/lib/plugin/medias/audio-capture.js +224 -0
  19. package/lib/plugin/medias/audio-playback.d.ts +13 -0
  20. package/lib/plugin/medias/audio-playback.js +40 -0
  21. package/lib/plugin/medias/video-capture.d.ts +15 -0
  22. package/lib/plugin/medias/video-capture.js +69 -0
  23. package/lib/plugin/medias/video-playback.d.ts +13 -0
  24. package/lib/plugin/medias/video-playback.js +20 -0
  25. package/{backend/lib → lib/plugin}/roomConnection.d.ts +9 -6
  26. package/{backend/lib → lib/plugin}/roomConnection.js +74 -53
  27. package/lib/plugin/rpcConnection.d.ts +57 -0
  28. package/{backend/lib → lib/plugin}/rpcConnection.js +129 -83
  29. package/lib/plugin/token.d.ts +13 -0
  30. package/{backend/lib → lib/plugin}/token.js +8 -9
  31. package/lib/plugin/webrtc/mainConnection.d.ts +53 -0
  32. package/lib/plugin/webrtc/mainConnection.js +455 -0
  33. package/lib/plugin/webrtc/websocket.d.ts +3 -0
  34. package/lib/plugin/webrtc/websocket.js +56 -0
  35. package/lib/worker/buffers.d.ts +42 -0
  36. package/lib/worker/buffers.js +79 -0
  37. package/{worker/lib/index.d.ts → lib/worker/common.d.ts} +7 -8
  38. package/lib/worker/common.js +7 -0
  39. package/lib/worker/config.d.ts +8 -0
  40. package/lib/worker/config.js +11 -0
  41. package/lib/worker/index.d.ts +3 -0
  42. package/lib/worker/index.js +1 -0
  43. package/lib/worker/memory.d.ts +9 -0
  44. package/lib/worker/memory.js +29 -0
  45. package/lib/worker/messages.d.ts +14 -0
  46. package/lib/worker/messages.js +15 -0
  47. package/lib/worker/packet.d.ts +11 -0
  48. package/lib/worker/packet.js +59 -0
  49. package/lib/worker/shared/capture.d.ts +27 -0
  50. package/lib/worker/shared/capture.js +63 -0
  51. package/lib/worker/shared/index.d.ts +3 -0
  52. package/lib/worker/shared/index.js +147 -0
  53. package/lib/worker/shared/messages.d.ts +67 -0
  54. package/lib/worker/shared/messages.js +64 -0
  55. package/lib/worker/shared/playback.d.ts +20 -0
  56. package/lib/worker/shared/playback.js +78 -0
  57. package/lib/worker/unshared/capture.d.ts +27 -0
  58. package/lib/worker/unshared/capture.js +66 -0
  59. package/lib/worker/unshared/index.d.ts +3 -0
  60. package/lib/worker/unshared/index.js +170 -0
  61. package/{worker/lib → lib/worker/unshared}/messages.d.ts +3 -15
  62. package/lib/worker/unshared/messages.js +80 -0
  63. package/lib/worker/unshared/playback.d.ts +22 -0
  64. package/lib/worker/unshared/playback.js +83 -0
  65. package/package.json +29 -26
  66. package/backend/lib/audioController.d.ts.map +0 -1
  67. package/backend/lib/audioController.js +0 -442
  68. package/backend/lib/audioController.js.map +0 -1
  69. package/backend/lib/config.d.ts.map +0 -1
  70. package/backend/lib/config.js +0 -11
  71. package/backend/lib/config.js.map +0 -1
  72. package/backend/lib/connectionPool.d.ts.map +0 -1
  73. package/backend/lib/connectionPool.js.map +0 -1
  74. package/backend/lib/index.d.ts.map +0 -1
  75. package/backend/lib/index.js +0 -293
  76. package/backend/lib/index.js.map +0 -1
  77. package/backend/lib/mainConnection.d.ts +0 -40
  78. package/backend/lib/mainConnection.d.ts.map +0 -1
  79. package/backend/lib/mainConnection.js +0 -294
  80. package/backend/lib/mainConnection.js.map +0 -1
  81. package/backend/lib/roomConnection.d.ts.map +0 -1
  82. package/backend/lib/roomConnection.js.map +0 -1
  83. package/backend/lib/rpcConnection.d.ts +0 -49
  84. package/backend/lib/rpcConnection.d.ts.map +0 -1
  85. package/backend/lib/rpcConnection.js.map +0 -1
  86. package/backend/lib/token.d.ts +0 -16
  87. package/backend/lib/token.d.ts.map +0 -1
  88. package/backend/lib/token.js.map +0 -1
  89. package/backend/package.json +0 -13
  90. package/wasm/lib/index.js +0 -19
  91. package/wasm/package.json +0 -14
  92. package/worker/lib/common.d.ts +0 -27
  93. package/worker/lib/index.js +0 -2
  94. package/worker/package.json +0 -13
  95. /package/{wasm/lib → lib/wasm}/index.d.ts +0 -0
@@ -1,19 +1,23 @@
1
+ import { Backend, RoomCommands, Result, Infer } from '@4players/odin-common';
1
2
  import { ConnectionPool } from './connectionPool';
2
3
  import { MainConnection } from './mainConnection';
3
4
  import { Token } from './token';
4
- import { Backend, RoomCommands, Result } from '@4players/odin-common';
5
- import * as z from 'zod';
6
- export declare class RoomConnection {
5
+ import { Transport } from './index';
6
+ export declare class RoomConnection implements RoomConnection {
7
7
  readonly connectionPool: ConnectionPool;
8
+ readonly transport: Transport;
8
9
  readonly onEvent: Backend.OnEvent;
9
10
  readonly gateway: URL | undefined;
10
11
  readonly roomId: string;
11
12
  private _RoomConnection;
12
13
  private _MainConnection;
14
+ private _OwnPeerId;
13
15
  private readonly _Close;
14
16
  private _Token;
15
17
  private _UserData;
16
18
  private _Position;
19
+ private _ConnectionFailures;
20
+ private _FailureLimit;
17
21
  private _LastTokenRenew;
18
22
  private readonly _Closed;
19
23
  get token(): Token;
@@ -21,9 +25,9 @@ export declare class RoomConnection {
21
25
  get position(): [number, number, number];
22
26
  get closed(): boolean;
23
27
  get mainConnection(): MainConnection | undefined;
24
- constructor(connectionPool: ConnectionPool, onEvent: Backend.OnEvent, gateway: URL | undefined, token: Token, roomId: string, userData: Uint8Array, position: [number, number, number]);
28
+ constructor(connectionPool: ConnectionPool, transport: Transport, onEvent: Backend.OnEvent, gateway: URL | undefined, token: Token, roomId: string, userData: Uint8Array, position: [number, number, number]);
25
29
  request(name: string, properties: unknown): Promise<Result<unknown> | 'closed'>;
26
- typedRequest<Name extends Extract<keyof RoomCommands, string>>(name: Name, properties: z.infer<RoomCommands[Name]['request']>): Promise<Result<z.infer<RoomCommands[Name]['response']>> | 'closed'>;
30
+ typedRequest<Name extends Extract<keyof RoomCommands, string>>(name: Name, properties: Infer<RoomCommands[Name]['request']>): Promise<Result<Infer<RoomCommands[Name]['response']>> | 'closed'>;
27
31
  close(): void;
28
32
  get renewTokenIn(): number;
29
33
  private _Main;
@@ -34,4 +38,3 @@ export declare class RoomConnection {
34
38
  private _HandleRequests;
35
39
  private _RenewToken;
36
40
  }
37
- //# sourceMappingURL=roomConnection.d.ts.map
@@ -7,11 +7,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { RpcConnection } from './rpcConnection';
10
+ import { Selector, failure, sleep, success, RoomCommandsRpc, RoomNotificationsRpc, } from '@4players/odin-common';
11
11
  import { Token } from './token';
12
- import { Selector, failure, sleep, success, RoomCommandsRpc, } from '@4players/odin-common';
13
- import * as z from 'zod';
14
- import { ConnectTimeout, MinTokenLifetime, MinTokenRefreshInterval, } from './config';
12
+ import { ConnectTimeout, logger, MinTokenLifetime, MinTokenRefreshInterval, } from './config';
15
13
  export class RoomConnection {
16
14
  get token() {
17
15
  return this._Token;
@@ -28,12 +26,15 @@ export class RoomConnection {
28
26
  get mainConnection() {
29
27
  return this._MainConnection;
30
28
  }
31
- constructor(connectionPool, onEvent, gateway, token, roomId, userData, position) {
29
+ constructor(connectionPool, transport, onEvent, gateway, token, roomId, userData, position) {
32
30
  this.connectionPool = connectionPool;
31
+ this.transport = transport;
33
32
  this.onEvent = onEvent;
34
33
  this.gateway = gateway;
35
34
  this.roomId = roomId;
36
35
  this._Close = new AbortController();
36
+ this._ConnectionFailures = 0;
37
+ this._FailureLimit = 5;
37
38
  this._LastTokenRenew = performance.now();
38
39
  this._Closed = new Promise((accept) => this._Close.signal.addEventListener('abort', () => accept('closed'), {
39
40
  once: true,
@@ -41,7 +42,7 @@ export class RoomConnection {
41
42
  this._Token = token;
42
43
  this._UserData = userData;
43
44
  this._Position = position;
44
- this._Main().then(({ reason }) => console.debug(`room closed; ${reason}`));
45
+ this._Main().then(({ reason }) => logger.info(['Connection'], `RoomConnection: Main() resolved; ${reason}`));
45
46
  }
46
47
  request(name, properties) {
47
48
  return __awaiter(this, void 0, void 0, function* () {
@@ -78,11 +79,12 @@ export class RoomConnection {
78
79
  return Math.max(earliest, latest);
79
80
  }
80
81
  _Main() {
81
- var _a;
82
82
  return __awaiter(this, void 0, void 0, function* () {
83
+ var _a;
83
84
  let closeReason = 'unable to establish connection';
84
85
  /// as long as we are asked to continue
85
86
  while (this._Close.signal.aborted === false) {
87
+ logger.debug(['Connection', 'RoomConnection._Main() loop']);
86
88
  const result = yield this._ConnectToServer();
87
89
  if (result.type === 'Failure') {
88
90
  closeReason = result.reason;
@@ -91,6 +93,7 @@ export class RoomConnection {
91
93
  (_a = this._RoomConnection) === null || _a === void 0 ? void 0 : _a.close();
92
94
  this._RoomConnection = undefined;
93
95
  this._MainConnection = undefined;
96
+ this._OwnPeerId = undefined;
94
97
  // can the token be used to request a better token from a gateway?
95
98
  if (this.gateway !== undefined && this._Token.hasAudience('gateway')) {
96
99
  this._ChangeStatus('Joining', `requesting new token from ${this.gateway}`);
@@ -122,32 +125,42 @@ export class RoomConnection {
122
125
  }
123
126
  _ConnectToServer() {
124
127
  return __awaiter(this, void 0, void 0, function* () {
125
- if (!this._Token.hasAudience('sfu') || this._Token.address === undefined) {
128
+ // for now strip upstream wrappers in the token, because it not supported in web
129
+ let token = this._Token;
130
+ while (token.upstream !== undefined) {
131
+ token = token.upstream;
132
+ }
133
+ if (!token.hasAudience('sfu') || token.claims.adr === undefined) {
126
134
  return success('continue');
127
135
  }
128
- this._ChangeStatus('Joining', `connecting to ${this._Token.address}`);
136
+ this._ChangeStatus('Joining', `connecting to ${token.claims.adr}`);
129
137
  // are we already connected to the server?
130
138
  if (this._MainConnection === undefined ||
131
139
  this._MainConnection.closed ||
132
- this._MainConnection.url !== this._Token.address) {
140
+ this._MainConnection.address !== token.claims.adr) {
133
141
  // no? release the not fitting connection
134
142
  if (this._MainConnection) {
135
143
  this.connectionPool.releaseConnection(this._MainConnection);
136
144
  }
137
145
  // connect to the right server
138
- const mainConnection = yield this.connectionPool.acquireConnection(this._Token.address, this._Close.signal);
146
+ const mainConnection = yield this.connectionPool.acquireConnection(this.transport, token.claims.adr, this._Close.signal);
139
147
  if (mainConnection === 'closed')
140
148
  return failure('connection pool closed'); // connection pool is closed
141
149
  if (mainConnection.type === 'Failure') {
150
+ if (this._ConnectionFailures < this._FailureLimit) {
151
+ this._ConnectionFailures++;
152
+ return failure(`Connection failed; ${mainConnection.reason}`);
153
+ }
142
154
  this._ChangeStatus('Joining', `connection failed; ${mainConnection.reason}`);
143
155
  return success('continue');
144
156
  }
145
157
  this._MainConnection = mainConnection.value;
158
+ this._OwnPeerId = undefined;
146
159
  }
147
160
  // join room
148
161
  const result = yield Promise.race([
149
162
  Promise.all([
150
- this._MainConnection.joinRoom(this._Token, this.roomId, this.userData, this.position),
163
+ this._MainConnection.joinRoom(token, this.roomId, this.userData, this.position),
151
164
  ]),
152
165
  sleep(ConnectTimeout, 'timeout'),
153
166
  this._Closed,
@@ -155,36 +168,37 @@ export class RoomConnection {
155
168
  if (result === 'closed')
156
169
  return failure('room connection closed'); // room connection was closed
157
170
  if (result !== 'timeout') {
158
- const [websocket] = result;
159
- if (websocket === 'closed')
171
+ const [rpc] = result;
172
+ if (rpc === 'closed')
160
173
  return success('continue'); // connection was lost, before joinRoom finished
161
- if (websocket.type === 'Failure') {
174
+ if (rpc.type === 'Failure') {
162
175
  // join was rejected by the server
163
- return failure(`unable to join room; ${websocket.reason}`);
176
+ return failure(`unable to join room; ${rpc.reason}`);
164
177
  }
165
178
  // room connection is open, make it available
166
- this._RoomConnection = new RpcConnection(websocket.value);
167
- this._ChangeStatus('Joined', `joined room ${this.roomId} on ${websocket.value.url}`);
179
+ this._RoomConnection = rpc.value;
180
+ this._ChangeStatus('Joined', `joined ${this.roomId}`);
168
181
  // TODO(sven): handle this
169
- // await this._MainConnection.webRtcReady()
170
- // process room events
171
- yield this._HandleConnection(this._MainConnection, websocket.value);
182
+ this._MainConnection
183
+ .waitForConnected()
184
+ .catch((error) => console.error('main connection failed to connect', error));
185
+ // Handle the open connection until it gets closed
186
+ yield this._HandleConnection(this._MainConnection);
172
187
  }
173
188
  // try to reconnect
174
189
  return success('continue');
175
190
  });
176
191
  }
177
192
  _ChangeStatus(status, message) {
178
- return __awaiter(this, void 0, void 0, function* () {
179
- const properties = {
180
- status,
181
- message,
182
- };
183
- this.onEvent('RoomStatusChanged', properties);
184
- });
193
+ const properties = {
194
+ status,
195
+ message,
196
+ };
197
+ this.onEvent('RoomStatusChanged', properties);
185
198
  }
186
- _HandleConnection(main, webSocket) {
199
+ _HandleConnection(main) {
187
200
  return __awaiter(this, void 0, void 0, function* () {
201
+ var _a;
188
202
  if (this._RoomConnection === undefined)
189
203
  return;
190
204
  const selector = new Selector([
@@ -199,10 +213,12 @@ export class RoomConnection {
199
213
  switch (value) {
200
214
  case undefined:
201
215
  case 'closed':
202
- webSocket.close();
216
+ logger.debug(['Connection'], 'RoomConnection._HandleConnection: closed');
217
+ (_a = this._RoomConnection) === null || _a === void 0 ? void 0 : _a.close();
218
+ this.connectionPool.releaseConnection(main);
203
219
  return;
204
220
  case 'renewToken':
205
- this._RenewToken(main, webSocket);
221
+ this._RenewToken();
206
222
  break;
207
223
  case 'tick':
208
224
  break;
@@ -214,12 +230,23 @@ export class RoomConnection {
214
230
  });
215
231
  }
216
232
  _HandleEvent(event) {
233
+ if (event.name === 'RoomUpdated') {
234
+ const roomUpdated = RoomNotificationsRpc.RoomUpdated.safeParse(event.properties);
235
+ if (!roomUpdated.success)
236
+ return;
237
+ for (const update of roomUpdated.data.updates) {
238
+ switch (update.kind) {
239
+ case 'Joined':
240
+ this._OwnPeerId = update.own_peer_id;
241
+ break;
242
+ }
243
+ }
244
+ }
217
245
  this.onEvent(event.name, event.properties);
218
246
  }
219
247
  _HandleRequests(name, properties, response) {
220
248
  switch (name) {
221
- case 'SetPeerPosition':
222
- // eslint-disable-next-line no-case-declarations
249
+ case 'SetPeerPosition': {
223
250
  const setPeerPosition = RoomCommandsRpc.SetPeerPosition.request.safeParse(properties);
224
251
  if (setPeerPosition.success) {
225
252
  const value = setPeerPosition.data.position;
@@ -229,8 +256,8 @@ export class RoomConnection {
229
256
  console.warn('unable to process SetPeerPosition command');
230
257
  }
231
258
  break;
232
- case 'UpdatePeer':
233
- // eslint-disable-next-line no-case-declarations
259
+ }
260
+ case 'UpdatePeer': {
234
261
  const updatePeer = RoomCommandsRpc.UpdatePeer.request.safeParse(properties);
235
262
  if (updatePeer.success) {
236
263
  this._UserData = updatePeer.data.user_data;
@@ -239,27 +266,33 @@ export class RoomConnection {
239
266
  console.warn('unable to process UpdatePeer command');
240
267
  }
241
268
  break;
269
+ }
242
270
  }
243
271
  }
244
- _RenewToken(main, webSocket) {
272
+ _RenewToken() {
245
273
  return __awaiter(this, void 0, void 0, function* () {
246
274
  this._LastTokenRenew = performance.now();
247
275
  if (this.token.timeLeft > MinTokenLifetime)
248
276
  return;
249
- const response = yield main.getReconnectToken(webSocket);
277
+ if (this._MainConnection === undefined || this._OwnPeerId === undefined) {
278
+ return failure('connection is not established');
279
+ }
280
+ const response = yield this._MainConnection.getReconnectToken(this._OwnPeerId);
250
281
  if (response.type === 'Success') {
251
282
  if (response.value.timeLeft > this._Token.timeLeft) {
252
283
  this._Token = response.value;
253
284
  }
285
+ return success();
254
286
  }
255
287
  else {
256
- console.warn(`${main.url} rejected reconnect token request; ${response.reason}`);
288
+ return failure(`${this._MainConnection.address} rejected reconnect token request; ${response.reason}`);
257
289
  }
258
290
  });
259
291
  }
260
292
  }
261
293
  function contactGateway(gateway, token, signal) {
262
294
  return __awaiter(this, void 0, void 0, function* () {
295
+ var _a, _b;
263
296
  try {
264
297
  const response = yield fetch(gateway, {
265
298
  body: '{"jsonrpc":"2.0","id":1,"method":"Connect","params":{}}',
@@ -270,24 +303,13 @@ function contactGateway(gateway, token, signal) {
270
303
  },
271
304
  signal,
272
305
  });
273
- const schema = z.union([
274
- z.object({
275
- result: z.object({
276
- token: z.string(),
277
- }),
278
- }),
279
- z.object({
280
- error: z.object({
281
- message: z.string(),
282
- }),
283
- }),
284
- ]);
285
- const body = schema.parse(yield response.json());
306
+ // TODO: re-add validation once schemas are available in common
307
+ const body = yield response.json();
286
308
  if ('result' in body) {
287
309
  return Token.parse(body.result.token);
288
310
  }
289
311
  else {
290
- console.error(`gateway rejected token; ${body.error.message}`);
312
+ console.error(`gateway rejected token; ${(_b = (_a = body.error) === null || _a === void 0 ? void 0 : _a.message) !== null && _b !== void 0 ? _b : 'malformed response'}`);
291
313
  return success('rejected');
292
314
  }
293
315
  }
@@ -296,4 +318,3 @@ function contactGateway(gateway, token, signal) {
296
318
  }
297
319
  });
298
320
  }
299
- //# sourceMappingURL=roomConnection.js.map
@@ -0,0 +1,57 @@
1
+ import { Result, Accept, MessagePackRpc, Notifications, Infer, Commands } from '@4players/odin-common';
2
+ export interface RpcMessage {
3
+ name: string;
4
+ properties: unknown;
5
+ }
6
+ export interface RpcRequest {
7
+ accept: Accept<Result<unknown> | 'closed' | 'timeout'>;
8
+ timeoutId: ReturnType<typeof setTimeout> | undefined;
9
+ }
10
+ export declare class RpcConnection {
11
+ private readonly stream;
12
+ private readonly _SendQueue;
13
+ private readonly _RecvQueue;
14
+ private readonly _EventQueue;
15
+ private readonly _Requests;
16
+ private readonly _Close;
17
+ private readonly _Writer;
18
+ private _NextId;
19
+ get closed(): boolean;
20
+ get closeSignal(): AbortSignal;
21
+ constructor(stream: WebSocket | WebTransportBidirectionalStream);
22
+ request(name: string, properties: unknown): Promise<Result<unknown> | 'closed'>;
23
+ request(name: string, properties: unknown, timeout: number): Promise<Result<unknown> | 'closed' | 'timeout'>;
24
+ notify(name: string, properties: unknown): void;
25
+ recv(): Promise<RpcMessage | 'closed'>;
26
+ close(): void;
27
+ private _TimeoutRequest;
28
+ private _Send;
29
+ private _OnWebSocketOpen;
30
+ private _OnRpcMessage;
31
+ private _OnResponse;
32
+ private _OnEvent;
33
+ private _Cleanup;
34
+ }
35
+ export interface TypedRpcMessage<Name extends string, Properties> extends RpcMessage {
36
+ name: Name;
37
+ properties: Properties;
38
+ }
39
+ export type RealizedEvents<E extends Notifications> = {
40
+ [Name in Extract<keyof E, string>]: TypedRpcMessage<Name, Infer<E[Name]>>;
41
+ }[Extract<keyof E, string>];
42
+ export declare class TypedRpcConnection<C extends Commands, E extends Notifications> {
43
+ readonly rpcConnection: RpcConnection;
44
+ private readonly _Commands;
45
+ private readonly _Events;
46
+ get closed(): boolean;
47
+ get closeSignal(): AbortSignal;
48
+ constructor(rpcConnection: RpcConnection, _Commands: C, _Events: E);
49
+ request<Name extends Extract<keyof C, string>>(name: Name, properties: Infer<C[Name]['request']>): Promise<Result<Infer<C[Name]['response']>> | 'closed'>;
50
+ request<Name extends Extract<keyof C, string>>(name: Name, properties: Infer<C[Name]['request']>, timeout: number): Promise<Result<Infer<C[Name]['response']>> | 'closed' | 'timeout'>;
51
+ notify<Name extends Extract<keyof C, string>>(name: Name, properties: Infer<C[Name]['request']>): void;
52
+ recv(): Promise<RealizedEvents<E> | 'closed'>;
53
+ close(): void;
54
+ }
55
+ export declare function parseRpc(buffer: ArrayBuffer): Result<MessagePackRpc>;
56
+ export declare function parseRpcMessage<E extends Notifications>(events: E, rpc: RpcMessage): RealizedEvents<E> | undefined;
57
+ export declare function isKnownRpcMessage<E extends Notifications>(events: E, name: string): name is Extract<keyof E, string>;