@meshagent/meshagent 0.37.2 → 0.38.0

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 (77) hide show
  1. package/CHANGELOG.md +3 -0
  2. package/dist/browser/agent.js +74 -10
  3. package/dist/browser/developer-client.js +3 -0
  4. package/dist/browser/helpers.d.ts +2 -2
  5. package/dist/browser/helpers.js +1 -1
  6. package/dist/browser/meshagent-client.d.ts +25 -0
  7. package/dist/browser/meshagent-client.js +65 -0
  8. package/dist/browser/messaging-client.d.ts +29 -16
  9. package/dist/browser/messaging-client.js +256 -154
  10. package/dist/browser/participant.d.ts +7 -2
  11. package/dist/browser/participant.js +9 -9
  12. package/dist/browser/protocol.d.ts +85 -28
  13. package/dist/browser/protocol.js +356 -119
  14. package/dist/browser/room-client.d.ts +165 -29
  15. package/dist/browser/room-client.js +1114 -74
  16. package/dist/browser/room-event.d.ts +11 -0
  17. package/dist/browser/room-event.js +21 -1
  18. package/dist/browser/room-server-client.d.ts +2 -0
  19. package/dist/browser/room-server-client.js +6 -0
  20. package/dist/browser/runtime.d.ts +1 -1
  21. package/dist/browser/runtime.js +3 -1
  22. package/dist/browser/secrets-client.js +6 -2
  23. package/dist/browser/storage-client.d.ts +1 -0
  24. package/dist/browser/storage-client.js +9 -0
  25. package/dist/browser/sync-client.d.ts +16 -14
  26. package/dist/browser/sync-client.js +195 -116
  27. package/dist/esm/agent.js +74 -10
  28. package/dist/esm/developer-client.js +3 -0
  29. package/dist/esm/helpers.d.ts +2 -2
  30. package/dist/esm/helpers.js +1 -1
  31. package/dist/esm/meshagent-client.d.ts +25 -0
  32. package/dist/esm/meshagent-client.js +65 -0
  33. package/dist/esm/messaging-client.d.ts +29 -16
  34. package/dist/esm/messaging-client.js +256 -154
  35. package/dist/esm/participant.d.ts +7 -2
  36. package/dist/esm/participant.js +9 -9
  37. package/dist/esm/protocol.d.ts +85 -28
  38. package/dist/esm/protocol.js +352 -118
  39. package/dist/esm/room-client.d.ts +165 -29
  40. package/dist/esm/room-client.js +1112 -73
  41. package/dist/esm/room-event.d.ts +11 -0
  42. package/dist/esm/room-event.js +19 -0
  43. package/dist/esm/room-server-client.d.ts +2 -0
  44. package/dist/esm/room-server-client.js +7 -1
  45. package/dist/esm/runtime.d.ts +1 -1
  46. package/dist/esm/runtime.js +1 -1
  47. package/dist/esm/secrets-client.js +6 -2
  48. package/dist/esm/storage-client.d.ts +1 -0
  49. package/dist/esm/storage-client.js +9 -0
  50. package/dist/esm/sync-client.d.ts +16 -14
  51. package/dist/esm/sync-client.js +196 -117
  52. package/dist/node/agent.js +74 -10
  53. package/dist/node/developer-client.js +3 -0
  54. package/dist/node/helpers.d.ts +2 -2
  55. package/dist/node/helpers.js +1 -1
  56. package/dist/node/meshagent-client.d.ts +25 -0
  57. package/dist/node/meshagent-client.js +65 -0
  58. package/dist/node/messaging-client.d.ts +29 -16
  59. package/dist/node/messaging-client.js +256 -154
  60. package/dist/node/participant.d.ts +7 -2
  61. package/dist/node/participant.js +9 -9
  62. package/dist/node/protocol.d.ts +85 -28
  63. package/dist/node/protocol.js +356 -119
  64. package/dist/node/room-client.d.ts +165 -29
  65. package/dist/node/room-client.js +1114 -74
  66. package/dist/node/room-event.d.ts +11 -0
  67. package/dist/node/room-event.js +21 -1
  68. package/dist/node/room-server-client.d.ts +2 -0
  69. package/dist/node/room-server-client.js +6 -0
  70. package/dist/node/runtime.d.ts +1 -1
  71. package/dist/node/runtime.js +3 -1
  72. package/dist/node/secrets-client.js +6 -2
  73. package/dist/node/storage-client.d.ts +1 -0
  74. package/dist/node/storage-client.js +9 -0
  75. package/dist/node/sync-client.d.ts +16 -14
  76. package/dist/node/sync-client.js +195 -116
  77. package/package.json +6 -3
@@ -1,15 +1,16 @@
1
- import { EventEmitter } from "./event-emitter";
2
1
  import { Completer } from "./completer";
2
+ import { EventEmitter } from "./event-emitter";
3
3
  import { RemoteParticipant } from "./participant";
4
+ import { JsonContent } from "./response";
4
5
  import { RoomMessage, RoomMessageEvent } from "./room-event";
5
6
  import { RoomServerException } from "./room-server-client";
6
7
  import { splitMessageHeader, splitMessagePayload } from "./utils";
7
8
  const globalScope = globalThis;
8
9
  function bytesToBase64(bytes) {
9
- if (globalScope.Buffer) {
10
+ if (globalScope.Buffer != null) {
10
11
  return globalScope.Buffer.from(bytes).toString("base64");
11
12
  }
12
- if (!globalScope.btoa) {
13
+ if (globalScope.btoa == null) {
13
14
  throw new Error("base64 encoding is not available in this runtime");
14
15
  }
15
16
  let binary = "";
@@ -27,10 +28,21 @@ export class MessagingClient extends EventEmitter {
27
28
  this._messageQueued = null;
28
29
  this._sendTask = null;
29
30
  this._messageQueueClosed = false;
30
- this._enabled = false;
31
+ this._desiredEnabled = false;
32
+ this._online = false;
33
+ this._enableInFlight = false;
31
34
  this.client = room;
32
35
  this.client.protocol.addHandler("messaging.send", this._messageHandler);
33
36
  }
37
+ get isEnabled() {
38
+ return this._desiredEnabled;
39
+ }
40
+ get online() {
41
+ return this._online;
42
+ }
43
+ get remoteParticipants() {
44
+ return Object.values(this._participants);
45
+ }
34
46
  _messageInput(params) {
35
47
  const input = {
36
48
  type: params.type,
@@ -44,16 +56,110 @@ export class MessagingClient extends EventEmitter {
44
56
  }
45
57
  return input;
46
58
  }
47
- _syntheticMessageEvent(params) {
48
- return new RoomMessageEvent({
49
- message: new RoomMessage({
50
- fromParticipantId: params.fromParticipantId,
51
- type: params.type,
52
- message: params.message,
53
- local: true,
54
- }),
59
+ async _invoke({ operation, input, }) {
60
+ await this.client.invoke({
61
+ toolkit: "messaging",
62
+ tool: operation,
63
+ input: new JsonContent({ json: input }),
64
+ });
65
+ }
66
+ _invokeNowait({ operation, input, }) {
67
+ this.client.invokeNowait({
68
+ toolkit: "messaging",
69
+ tool: operation,
70
+ input: new JsonContent({ json: input }),
55
71
  });
56
72
  }
73
+ start() {
74
+ if (this._sendTask != null) {
75
+ return;
76
+ }
77
+ this._messageQueueClosed = false;
78
+ this._sendTask = this._sendMessages();
79
+ if (this._desiredEnabled && this.client.isConnected) {
80
+ this._enableCurrentConnectionNowait();
81
+ }
82
+ }
83
+ async stop() {
84
+ const stoppedError = this.client._messageStopError();
85
+ this._messageQueueClosed = true;
86
+ this._wakeMessageQueue();
87
+ this._drainQueuedMessages({ error: stoppedError });
88
+ const sendTask = this._sendTask;
89
+ this._sendTask = null;
90
+ if (sendTask != null) {
91
+ await sendTask;
92
+ }
93
+ this._desiredEnabled = false;
94
+ this._clearCurrentConnectionState();
95
+ }
96
+ async _nextQueuedMessage() {
97
+ while (true) {
98
+ if (this._messageQueue.length > 0) {
99
+ return this._messageQueue.shift() ?? null;
100
+ }
101
+ if (this._messageQueueClosed) {
102
+ return null;
103
+ }
104
+ this._messageQueued ?? (this._messageQueued = new Completer());
105
+ await this._messageQueued.fut;
106
+ }
107
+ }
108
+ _wakeMessageQueue() {
109
+ const signal = this._messageQueued;
110
+ this._messageQueued = null;
111
+ if (signal != null && !signal.completed) {
112
+ signal.complete();
113
+ }
114
+ }
115
+ _queueMessage(message) {
116
+ if (this._messageQueueClosed) {
117
+ throw new RoomServerException("Cannot send messages because messaging has been stopped");
118
+ }
119
+ this._messageQueue.push(message);
120
+ this._wakeMessageQueue();
121
+ }
122
+ _setOnline(online) {
123
+ if (this._online === online) {
124
+ return;
125
+ }
126
+ this._online = online;
127
+ }
128
+ async _waitUntilOnline() {
129
+ while (!this._online) {
130
+ if (!this.client.isConnected && !this.client._allowDisconnectedRequests) {
131
+ await this.client._waitUntilConnectedForMessages();
132
+ continue;
133
+ }
134
+ this.client._raiseIfTerminalForMessages();
135
+ await new Promise((resolve) => setTimeout(resolve, 50));
136
+ }
137
+ }
138
+ _enableCurrentConnectionNowait() {
139
+ if (this._online || this._enableInFlight) {
140
+ return;
141
+ }
142
+ this._enableInFlight = true;
143
+ this._invokeNowait({ operation: "enable", input: {} });
144
+ }
145
+ _clearCurrentConnectionState() {
146
+ this._enableInFlight = false;
147
+ this._setOnline(false);
148
+ if (Object.keys(this._participants).length === 0) {
149
+ return;
150
+ }
151
+ for (const participantId of Object.keys(this._participants)) {
152
+ this._removeParticipant(participantId);
153
+ }
154
+ }
155
+ _onRoomDisconnect({ reason: _reason }) {
156
+ this._clearCurrentConnectionState();
157
+ }
158
+ _onRoomReconnect() {
159
+ if (this._desiredEnabled) {
160
+ this._enableCurrentConnectionNowait();
161
+ }
162
+ }
57
163
  _removeParticipant(participantId) {
58
164
  const participant = this._participants[participantId];
59
165
  if (participant === undefined) {
@@ -68,18 +174,14 @@ export class MessagingClient extends EventEmitter {
68
174
  return;
69
175
  }
70
176
  participant._setOnline(false);
71
- const current = this._participants[participant.id];
72
- if (current === undefined) {
73
- return;
177
+ if (this._participants[participant.id] !== undefined) {
178
+ this._removeParticipant(participant.id);
74
179
  }
75
- this._removeParticipant(participant.id);
76
- this.emit("participant_removed", this._syntheticMessageEvent({
77
- fromParticipantId: participant.id,
78
- type: "participant.disabled",
79
- message: { id: participant.id },
80
- }));
81
180
  }
82
181
  _resolveMessageRecipient(to) {
182
+ if (to == null) {
183
+ return null;
184
+ }
83
185
  if (!(to instanceof RemoteParticipant)) {
84
186
  return to;
85
187
  }
@@ -88,116 +190,100 @@ export class MessagingClient extends EventEmitter {
88
190
  }
89
191
  return this._participants[to.id] ?? null;
90
192
  }
91
- _queueMessage(message) {
92
- if (this._sendTask === null) {
93
- throw new RoomServerException("Cannot send messages because messaging has not been started");
94
- }
95
- this._messageQueue.push(message);
96
- const waiter = this._messageQueued;
97
- if (waiter !== null) {
98
- this._messageQueued = null;
99
- waiter.complete();
193
+ _dropQueuedMessage({ message, error, }) {
194
+ if (message.completer != null && !message.completer.completed) {
195
+ message.completer.completeError(error);
100
196
  }
101
197
  }
102
- _rejectQueuedMessages(error) {
198
+ _drainQueuedMessages({ error }) {
103
199
  while (this._messageQueue.length > 0) {
104
- const message = this._messageQueue.shift();
105
- message?.completer?.completeError(error);
106
- }
107
- }
108
- _isParticipantNotFound(error) {
109
- return error instanceof RoomServerException && error.message === "the participant was not found";
110
- }
111
- async _nextQueuedMessage() {
112
- while (this._messageQueue.length === 0) {
113
- if (this._messageQueueClosed) {
114
- return null;
115
- }
116
- if (this._messageQueued === null) {
117
- this._messageQueued = new Completer();
200
+ const queued = this._messageQueue.shift();
201
+ if (queued != null) {
202
+ this._dropQueuedMessage({ message: queued, error });
118
203
  }
119
- await this._messageQueued.fut;
120
204
  }
121
- return this._messageQueue.shift() ?? null;
122
205
  }
123
206
  async _sendMessages() {
124
207
  while (true) {
125
- const queued = await this._nextQueuedMessage();
126
- if (queued === null) {
208
+ const message = await this._nextQueuedMessage();
209
+ if (message == null) {
127
210
  return;
128
211
  }
129
- const resolvedTo = this._resolveMessageRecipient(queued.to);
130
- if (resolvedTo === null) {
131
- const error = new RoomServerException("the participant was not found");
132
- if (queued.dropIfOffline) {
133
- queued.completer?.complete();
212
+ try {
213
+ await this.client._waitUntilConnectedForMessages();
214
+ if (this._desiredEnabled) {
215
+ await this._waitUntilOnline();
216
+ }
217
+ }
218
+ catch (error) {
219
+ if (error instanceof RoomServerException) {
220
+ this._dropQueuedMessage({ message, error });
221
+ this._drainQueuedMessages({ error });
134
222
  }
135
223
  else {
136
- queued.completer?.completeError(error);
224
+ const wrapped = new RoomServerException(String(error));
225
+ this._dropQueuedMessage({ message, error: wrapped });
226
+ this._drainQueuedMessages({ error: wrapped });
137
227
  }
228
+ return;
229
+ }
230
+ const resolvedTo = this._resolveMessageRecipient(message.to);
231
+ if (resolvedTo == null) {
232
+ this._dropQueuedMessage({
233
+ message,
234
+ error: new RoomServerException("the participant was not found"),
235
+ });
138
236
  continue;
139
237
  }
140
238
  try {
141
- await this.client.invoke({
142
- toolkit: "messaging",
143
- tool: "send",
239
+ await this._invoke({
240
+ operation: "send",
144
241
  input: this._messageInput({
145
242
  toParticipantId: resolvedTo.id,
146
- type: queued.type,
147
- message: queued.message,
148
- attachment: queued.attachment,
243
+ type: message.type,
244
+ message: message.message,
245
+ attachment: message.attachment,
149
246
  }),
150
247
  });
151
- queued.completer?.complete();
248
+ if (message.completer != null && !message.completer.completed) {
249
+ message.completer.complete();
250
+ }
152
251
  }
153
252
  catch (error) {
154
- if (this._isParticipantNotFound(error)) {
155
- this._markParticipantOffline(queued.to);
156
- if (queued.dropIfOffline) {
157
- queued.completer?.complete();
253
+ if (error instanceof RoomServerException) {
254
+ const wrapped = this.client._coerceMessageSendError(error);
255
+ if (wrapped.message === "the participant was not found") {
256
+ this._markParticipantOffline(message.to);
257
+ this._dropQueuedMessage({ message, error: wrapped });
158
258
  continue;
159
259
  }
260
+ this._dropQueuedMessage({ message, error: wrapped });
261
+ continue;
262
+ }
263
+ if (message.completer != null && !message.completer.completed) {
264
+ message.completer.completeError(error);
160
265
  }
161
- queued.completer?.completeError(error);
162
266
  }
163
267
  }
164
268
  }
165
- async start() {
166
- if (this._sendTask !== null) {
167
- return;
168
- }
169
- this._messageQueueClosed = false;
170
- this._sendTask = this._sendMessages();
171
- }
172
- async stop() {
173
- if (this._sendTask === null) {
174
- this._enabled = false;
175
- return;
176
- }
177
- this._messageQueueClosed = true;
178
- const waiter = this._messageQueued;
179
- if (waiter !== null) {
180
- this._messageQueued = null;
181
- waiter.complete();
269
+ async sendMessage({ to, type, message, attachment, ignoreOffline = false, }) {
270
+ if (this._sendTask == null) {
271
+ throw new RoomServerException("Cannot send messages because messaging has not been started");
182
272
  }
183
- const sendTask = this._sendTask;
184
- this._sendTask = null;
185
- await sendTask;
186
- this._enabled = false;
187
- }
188
- async sendMessage({ to, type, message, attachment, ignoreOffline = false }) {
189
- const completer = new Completer();
190
- this._queueMessage({
273
+ const queued = {
191
274
  to,
192
275
  type,
193
276
  message,
194
277
  attachment,
195
278
  dropIfOffline: ignoreOffline,
196
- completer,
197
- });
198
- await completer.fut;
279
+ completer: ignoreOffline ? undefined : new Completer(),
280
+ };
281
+ this._queueMessage(queued);
282
+ if (queued.completer != null) {
283
+ await queued.completer.fut;
284
+ }
199
285
  }
200
- sendMessageNowait({ to, type, message, attachment }) {
286
+ sendMessageNowait({ to, type, message, attachment, }) {
201
287
  this._queueMessage({
202
288
  to,
203
289
  type,
@@ -206,34 +292,40 @@ export class MessagingClient extends EventEmitter {
206
292
  dropIfOffline: true,
207
293
  });
208
294
  }
209
- async enable() {
210
- await this.client.invoke({
211
- toolkit: "messaging",
212
- tool: "enable",
213
- input: {},
214
- });
215
- this._enabled = true;
216
- }
217
- async disable() {
218
- await this.client.invoke({
219
- toolkit: "messaging",
220
- tool: "disable",
221
- input: {},
222
- });
223
- this._enabled = false;
224
- }
225
- async broadcastMessage({ type, message, attachment }) {
226
- await this.client.invoke({
227
- toolkit: "messaging",
228
- tool: "broadcast",
229
- input: this._messageInput({ type, message, attachment }),
230
- });
295
+ enable() {
296
+ this._desiredEnabled = true;
297
+ if (this.client.isConnected) {
298
+ this._enableCurrentConnectionNowait();
299
+ }
231
300
  }
232
- get remoteParticipants() {
233
- return Object.values(this._participants);
301
+ disable() {
302
+ const wasOnline = this._online;
303
+ this._desiredEnabled = false;
304
+ this._clearCurrentConnectionState();
305
+ if (this.client.isConnected && wasOnline) {
306
+ this._invokeNowait({ operation: "disable", input: {} });
307
+ }
234
308
  }
235
- get isEnabled() {
236
- return this._enabled;
309
+ async broadcastMessage({ type, message, attachment, }) {
310
+ if (this._sendTask == null) {
311
+ throw new RoomServerException("Cannot send messages because messaging has not been started");
312
+ }
313
+ await this.client._waitUntilConnectedForMessages();
314
+ if (this._desiredEnabled) {
315
+ await this._waitUntilOnline();
316
+ }
317
+ try {
318
+ await this._invoke({
319
+ operation: "broadcast",
320
+ input: this._messageInput({ type, message, attachment }),
321
+ });
322
+ }
323
+ catch (error) {
324
+ if (error instanceof RoomServerException) {
325
+ throw this.client._coerceMessageSendError(error);
326
+ }
327
+ throw error;
328
+ }
237
329
  }
238
330
  getParticipants() {
239
331
  return this.remoteParticipants;
@@ -249,15 +341,18 @@ export class MessagingClient extends EventEmitter {
249
341
  }
250
342
  return null;
251
343
  }
252
- async _handleMessageSend(protocol, messageId, type, bytes) {
253
- const headerStr = splitMessageHeader(bytes || new Uint8Array());
254
- const payload = splitMessagePayload(bytes || new Uint8Array());
344
+ async _handleMessageSend(protocol, _messageId, _type, bytes) {
345
+ if (!this.client.isActiveProtocol(protocol)) {
346
+ return;
347
+ }
348
+ const headerStr = splitMessageHeader(bytes);
349
+ const payload = splitMessagePayload(bytes);
255
350
  const header = JSON.parse(headerStr);
256
351
  const message = new RoomMessage({
257
352
  fromParticipantId: header["from_participant_id"],
258
353
  type: header["type"],
259
354
  message: header["message"],
260
- attachment: payload,
355
+ attachment: payload.length > 0 ? payload : undefined,
261
356
  });
262
357
  switch (message.type) {
263
358
  case "messaging.enabled":
@@ -272,54 +367,61 @@ export class MessagingClient extends EventEmitter {
272
367
  case "participant.disabled":
273
368
  this._onParticipantDisabled(message);
274
369
  break;
370
+ default:
371
+ break;
275
372
  }
276
- const messageEvent = new RoomMessageEvent({ message });
277
- this.client.emit(messageEvent);
278
- this.emit("message", messageEvent);
373
+ const event = new RoomMessageEvent({ message });
374
+ this.client.emit(event);
375
+ this.emit("message", event);
279
376
  }
280
377
  _onParticipantEnabled(message) {
281
378
  const data = message.message;
282
- const p = new RemoteParticipant(this.client, data["id"], data["role"], true);
283
- p._setAttributes(data["attributes"] ?? {});
284
- this._participants[data["id"]] = p;
285
- this.emit("participant_added", { message });
379
+ const participant = new RemoteParticipant(this.client, data.id, data.role, true);
380
+ participant._setAttributes(data.attributes ?? {});
381
+ this._participants[data.id] = participant;
382
+ this.emit("participant_added", new RoomMessageEvent({ message }));
286
383
  }
287
384
  _onParticipantAttributes(message) {
288
- const part = this._participants[message.fromParticipantId];
289
- if (!part) {
385
+ const participant = this._participants[message.fromParticipantId];
386
+ if (participant == null) {
290
387
  return;
291
388
  }
292
- const attrObj = message.message["attributes"];
293
- part._setAttributes(attrObj);
294
- this.emit("participant_attributes_updated", { message });
389
+ participant._setAttributes(message.message["attributes"]);
390
+ this.emit("participant_attributes_updated", new RoomMessageEvent({ message }));
295
391
  }
296
392
  _onParticipantDisabled(message) {
297
- const part = this._removeParticipant(message.message["id"]);
298
- if (part) {
299
- this.emit("participant_removed", { message });
393
+ const removed = this._removeParticipant(String(message.message["id"]));
394
+ if (removed != null) {
395
+ this.emit("participant_removed", new RoomMessageEvent({ message }));
300
396
  }
301
397
  }
302
398
  _onMessagingEnabled(message) {
399
+ this._enableInFlight = false;
400
+ for (const participantId of Object.keys(this._participants)) {
401
+ delete this._participants[participantId];
402
+ }
303
403
  const participants = message.message["participants"];
304
404
  for (const data of participants) {
305
- const rp = new RemoteParticipant(this.client, data["id"], data["role"], true);
306
- rp._setAttributes(data["attributes"] ?? {});
307
- this._participants[data["id"]] = rp;
405
+ const participant = new RemoteParticipant(this.client, data.id, data.role, true);
406
+ participant._setAttributes(data.attributes ?? {});
407
+ this._participants[data.id] = participant;
408
+ }
409
+ this._setOnline(true);
410
+ if (!this._desiredEnabled) {
411
+ this._invokeNowait({ operation: "disable", input: {} });
412
+ this._clearCurrentConnectionState();
413
+ return;
308
414
  }
309
- this._enabled = true;
310
- this.emit("messaging_enabled", { message });
415
+ this.emit("messaging_enabled", new RoomMessageEvent({ message }));
311
416
  }
312
417
  dispose() {
313
418
  const error = new RoomServerException("messaging client disposed");
314
419
  this._messageQueueClosed = true;
315
- this._enabled = false;
316
- this._rejectQueuedMessages(error);
317
- const waiter = this._messageQueued;
318
- if (waiter !== null) {
319
- this._messageQueued = null;
320
- waiter.complete();
321
- }
420
+ this._wakeMessageQueue();
421
+ this._drainQueuedMessages({ error });
422
+ this._desiredEnabled = false;
423
+ this._clearCurrentConnectionState();
424
+ this.client.protocol.removeHandler("messaging.send", this._messageHandler);
322
425
  super.dispose();
323
- this.client.protocol.removeHandler("messaging.send");
324
426
  }
325
427
  }
@@ -1,14 +1,19 @@
1
1
  import { RoomClient } from "./room-client";
2
2
  export declare abstract class Participant {
3
- readonly id: string;
3
+ id: string;
4
4
  protected readonly client: RoomClient;
5
5
  protected _attributes: Record<string, unknown>;
6
6
  protected _connections: string[];
7
7
  constructor(client: RoomClient, id: string);
8
8
  get connections(): ReadonlyArray<string>;
9
9
  getAttribute(name: string): unknown;
10
+ _replaceIdentity({ participantId, attributes, }: {
11
+ participantId: string;
12
+ attributes: Record<string, unknown>;
13
+ }): void;
10
14
  _setAttribute(name: string, value: unknown): void;
11
15
  _setAttributes(attributes: Record<string, unknown>): void;
16
+ _attributesSnapshot(): Record<string, unknown>;
12
17
  }
13
18
  export declare class RemoteParticipant extends Participant {
14
19
  readonly role: string;
@@ -18,5 +23,5 @@ export declare class RemoteParticipant extends Participant {
18
23
  }
19
24
  export declare class LocalParticipant extends Participant {
20
25
  constructor(client: RoomClient, id: string);
21
- setAttribute(name: string, value: unknown): Promise<void>;
26
+ setAttribute(name: string, value: unknown): void;
22
27
  }
@@ -1,4 +1,3 @@
1
- import { packMessage } from "./utils";
2
1
  export class Participant {
3
2
  constructor(client, id) {
4
3
  this._attributes = {};
@@ -12,6 +11,10 @@ export class Participant {
12
11
  getAttribute(name) {
13
12
  return this._attributes[name];
14
13
  }
14
+ _replaceIdentity({ participantId, attributes, }) {
15
+ this.id = participantId;
16
+ this._attributes = { ...attributes };
17
+ }
15
18
  _setAttribute(name, value) {
16
19
  this._attributes[name] = value;
17
20
  }
@@ -20,6 +23,9 @@ export class Participant {
20
23
  this._setAttribute(name, value);
21
24
  }
22
25
  }
26
+ _attributesSnapshot() {
27
+ return { ...this._attributes };
28
+ }
23
29
  }
24
30
  export class RemoteParticipant extends Participant {
25
31
  constructor(client, id, role, online) {
@@ -35,14 +41,8 @@ export class LocalParticipant extends Participant {
35
41
  constructor(client, id) {
36
42
  super(client, id);
37
43
  }
38
- async setAttribute(name, value) {
44
+ setAttribute(name, value) {
39
45
  this._setAttribute(name, value);
40
- try {
41
- const payload = packMessage({ [name]: value });
42
- await this.client.protocol.send("set_attributes", payload);
43
- }
44
- catch (err) {
45
- console.warn("Unable to send attribute changes", err);
46
- }
46
+ this.client._sendLocalAttributesNowait({ [name]: value });
47
47
  }
48
48
  }