@dxos/edge-client 0.8.4-main.a4bbb77 → 0.8.4-main.ae835ea

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 (33) hide show
  1. package/dist/lib/browser/{chunk-IKP53CBQ.mjs → chunk-VESGVCLQ.mjs} +15 -44
  2. package/dist/lib/browser/{chunk-IKP53CBQ.mjs.map → chunk-VESGVCLQ.mjs.map} +2 -2
  3. package/dist/lib/browser/edge-ws-muxer.mjs +1 -1
  4. package/dist/lib/browser/index.mjs +247 -156
  5. package/dist/lib/browser/index.mjs.map +3 -3
  6. package/dist/lib/browser/meta.json +1 -1
  7. package/dist/lib/browser/testing/index.mjs +1 -1
  8. package/dist/lib/browser/testing/index.mjs.map +2 -2
  9. package/dist/lib/node-esm/{chunk-DR5YNW5K.mjs → chunk-JTBFRYNM.mjs} +15 -44
  10. package/dist/lib/node-esm/{chunk-DR5YNW5K.mjs.map → chunk-JTBFRYNM.mjs.map} +2 -2
  11. package/dist/lib/node-esm/edge-ws-muxer.mjs +1 -1
  12. package/dist/lib/node-esm/index.mjs +247 -156
  13. package/dist/lib/node-esm/index.mjs.map +3 -3
  14. package/dist/lib/node-esm/meta.json +1 -1
  15. package/dist/lib/node-esm/testing/index.mjs +1 -1
  16. package/dist/lib/node-esm/testing/index.mjs.map +2 -2
  17. package/dist/types/src/edge-client.d.ts.map +1 -1
  18. package/dist/types/src/edge-http-client.d.ts +1 -0
  19. package/dist/types/src/edge-http-client.d.ts.map +1 -1
  20. package/dist/types/src/edge-ws-connection.d.ts +19 -0
  21. package/dist/types/src/edge-ws-connection.d.ts.map +1 -1
  22. package/dist/types/src/http-client.d.ts +10 -7
  23. package/dist/types/src/http-client.d.ts.map +1 -1
  24. package/dist/types/src/testing/test-utils.d.ts +1 -1
  25. package/dist/types/tsconfig.tsbuildinfo +1 -1
  26. package/package.json +14 -14
  27. package/src/edge-client.test.ts +4 -4
  28. package/src/edge-client.ts +36 -5
  29. package/src/edge-http-client.ts +24 -20
  30. package/src/edge-ws-connection.ts +118 -5
  31. package/src/http-client.test.ts +6 -4
  32. package/src/http-client.ts +13 -7
  33. package/src/testing/test-utils.ts +3 -3
@@ -7,7 +7,7 @@ import {
7
7
  getTypename,
8
8
  protocol,
9
9
  toUint8Array
10
- } from "./chunk-DR5YNW5K.mjs";
10
+ } from "./chunk-JTBFRYNM.mjs";
11
11
 
12
12
  // src/index.ts
13
13
  export * from "@dxos/protocols/buf/dxos/edge/messenger_pb";
@@ -124,7 +124,7 @@ var createStubEdgeIdentity = () => {
124
124
  };
125
125
 
126
126
  // src/edge-client.ts
127
- import { Event, PersistentLifecycle, Trigger, TriggerState, scheduleMicroTask } from "@dxos/async";
127
+ import { Event, PersistentLifecycle, Trigger, TriggerState, scheduleMicroTask, scheduleTaskInterval as scheduleTaskInterval2 } from "@dxos/async";
128
128
  import { Resource as Resource2 } from "@dxos/context";
129
129
  import { log as log2, logInfo as logInfo2 } from "@dxos/log";
130
130
  import { EdgeStatus } from "@dxos/protocols/proto/dxos/client/services";
@@ -178,19 +178,6 @@ import { log, logInfo } from "@dxos/log";
178
178
  import { EdgeWebsocketProtocol } from "@dxos/protocols";
179
179
  import { buf } from "@dxos/protocols/buf";
180
180
  import { MessageSchema } from "@dxos/protocols/buf/dxos/edge/messenger_pb";
181
- function _define_property(obj, key, value) {
182
- if (key in obj) {
183
- Object.defineProperty(obj, key, {
184
- value,
185
- enumerable: true,
186
- configurable: true,
187
- writable: true
188
- });
189
- } else {
190
- obj[key] = value;
191
- }
192
- return obj;
193
- }
194
181
  function _ts_decorate(decorators, target, key, desc) {
195
182
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
196
183
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -201,6 +188,28 @@ var __dxlog_file3 = "/__w/dxos/dxos/packages/core/mesh/edge-client/src/edge-ws-c
201
188
  var SIGNAL_KEEPALIVE_INTERVAL = 4e3;
202
189
  var SIGNAL_KEEPALIVE_TIMEOUT = 12e3;
203
190
  var EdgeWsConnection = class extends Resource {
191
+ _identity;
192
+ _connectionInfo;
193
+ _callbacks;
194
+ _inactivityTimeoutCtx;
195
+ _ws;
196
+ _wsMuxer;
197
+ _lastReceivedMessageTimestamp = Date.now();
198
+ _openTimestamp;
199
+ // Latency tracking.
200
+ _pingTimestamp;
201
+ _rtt = 0;
202
+ // Rate tracking with sliding window.
203
+ _uploadRate = 0;
204
+ _downloadRate = 0;
205
+ _rateWindow = 1e4;
206
+ _rateUpdateInterval = 1e3;
207
+ _bytesSamples = [];
208
+ _messagesSent = 0;
209
+ _messagesReceived = 0;
210
+ constructor(_identity, _connectionInfo, _callbacks) {
211
+ super(), this._identity = _identity, this._connectionInfo = _connectionInfo, this._callbacks = _callbacks;
212
+ }
204
213
  get info() {
205
214
  return {
206
215
  open: this.isOpen,
@@ -208,10 +217,28 @@ var EdgeWsConnection = class extends Resource {
208
217
  device: this._identity.peerKey
209
218
  };
210
219
  }
220
+ get rtt() {
221
+ return this._rtt;
222
+ }
223
+ get uptime() {
224
+ return this._openTimestamp ? (Date.now() - this._openTimestamp) / 1e3 : 0;
225
+ }
226
+ get uploadRate() {
227
+ return this._uploadRate;
228
+ }
229
+ get downloadRate() {
230
+ return this._downloadRate;
231
+ }
232
+ get messagesSent() {
233
+ return this._messagesSent;
234
+ }
235
+ get messagesReceived() {
236
+ return this._messagesReceived;
237
+ }
211
238
  send(message) {
212
239
  invariant3(this._ws, void 0, {
213
240
  F: __dxlog_file3,
214
- L: 53,
241
+ L: 93,
215
242
  S: this,
216
243
  A: [
217
244
  "this._ws",
@@ -220,7 +247,7 @@ var EdgeWsConnection = class extends Resource {
220
247
  });
221
248
  invariant3(this._wsMuxer, void 0, {
222
249
  F: __dxlog_file3,
223
- L: 54,
250
+ L: 94,
224
251
  S: this,
225
252
  A: [
226
253
  "this._wsMuxer",
@@ -232,10 +259,11 @@ var EdgeWsConnection = class extends Resource {
232
259
  payload: protocol.getPayloadType(message)
233
260
  }, {
234
261
  F: __dxlog_file3,
235
- L: 55,
262
+ L: 95,
236
263
  S: this,
237
264
  C: (f, a) => f(...a)
238
265
  });
266
+ this._messagesSent++;
239
267
  if (this._ws?.protocol.includes(EdgeWebsocketProtocol.V0)) {
240
268
  const binary = buf.toBinary(MessageSchema, message);
241
269
  if (binary.length > CLOUDFLARE_MESSAGE_MAX_BYTES) {
@@ -245,17 +273,20 @@ var EdgeWsConnection = class extends Resource {
245
273
  payload: protocol.getPayloadType(message)
246
274
  }, {
247
275
  F: __dxlog_file3,
248
- L: 59,
276
+ L: 100,
249
277
  S: this,
250
278
  C: (f, a) => f(...a)
251
279
  });
252
280
  return;
253
281
  }
282
+ this._recordBytes(binary.byteLength, 0);
254
283
  this._ws.send(binary);
255
284
  } else {
285
+ const binary = buf.toBinary(MessageSchema, message);
286
+ this._recordBytes(binary.byteLength, 0);
256
287
  this._wsMuxer.send(message).catch((e) => log.catch(e, void 0, {
257
288
  F: __dxlog_file3,
258
- L: 68,
289
+ L: 113,
259
290
  S: this,
260
291
  C: (f, a) => f(...a)
261
292
  }));
@@ -277,18 +308,20 @@ var EdgeWsConnection = class extends Resource {
277
308
  if (this.isOpen) {
278
309
  log("connected", void 0, {
279
310
  F: __dxlog_file3,
280
- L: 85,
311
+ L: 130,
281
312
  S: this,
282
313
  C: (f, a) => f(...a)
283
314
  });
315
+ this._openTimestamp = Date.now();
284
316
  this._callbacks.onConnected();
285
317
  this._scheduleHeartbeats();
318
+ this._scheduleRateCalculation();
286
319
  } else {
287
320
  log.verbose("connected after becoming inactive", {
288
321
  currentIdentity: this._identity
289
322
  }, {
290
323
  F: __dxlog_file3,
291
- L: 89,
324
+ L: 136,
292
325
  S: this,
293
326
  C: (f, a) => f(...a)
294
327
  });
@@ -296,12 +329,12 @@ var EdgeWsConnection = class extends Resource {
296
329
  };
297
330
  this._ws.onclose = (event) => {
298
331
  if (this.isOpen) {
299
- log.warn("disconnected while being open", {
332
+ log.warn("server disconnected", {
300
333
  code: event.code,
301
334
  reason: event.reason
302
335
  }, {
303
336
  F: __dxlog_file3,
304
- L: 94,
337
+ L: 141,
305
338
  S: this,
306
339
  C: (f, a) => f(...a)
307
340
  });
@@ -316,7 +349,7 @@ var EdgeWsConnection = class extends Resource {
316
349
  info: event.message
317
350
  }, {
318
351
  F: __dxlog_file3,
319
- L: 101,
352
+ L: 148,
320
353
  S: this,
321
354
  C: (f, a) => f(...a)
322
355
  });
@@ -326,7 +359,7 @@ var EdgeWsConnection = class extends Resource {
326
359
  error: event.error
327
360
  }, {
328
361
  F: __dxlog_file3,
329
- L: 104,
362
+ L: 151,
330
363
  S: this,
331
364
  C: (f, a) => f(...a)
332
365
  });
@@ -338,7 +371,7 @@ var EdgeWsConnection = class extends Resource {
338
371
  event: event.type
339
372
  }, {
340
373
  F: __dxlog_file3,
341
- L: 112,
374
+ L: 159,
342
375
  S: this,
343
376
  C: (f, a) => f(...a)
344
377
  });
@@ -346,13 +379,19 @@ var EdgeWsConnection = class extends Resource {
346
379
  }
347
380
  this._lastReceivedMessageTimestamp = Date.now();
348
381
  if (event.data === "__pong__") {
382
+ if (this._pingTimestamp) {
383
+ this._rtt = Date.now() - this._pingTimestamp;
384
+ this._pingTimestamp = void 0;
385
+ }
349
386
  this._rescheduleHeartbeatTimeout();
350
387
  return;
351
388
  }
352
389
  const bytes = await toUint8Array(event.data);
390
+ this._recordBytes(0, bytes.byteLength);
353
391
  if (!this.isOpen) {
354
392
  return;
355
393
  }
394
+ this._messagesReceived++;
356
395
  const message = this._ws?.protocol?.includes(EdgeWebsocketProtocol.V0) ? buf.fromBinary(MessageSchema, bytes) : muxer.receiveData(bytes);
357
396
  if (message) {
358
397
  log("received", {
@@ -360,7 +399,7 @@ var EdgeWsConnection = class extends Resource {
360
399
  payload: protocol.getPayloadType(message)
361
400
  }, {
362
401
  F: __dxlog_file3,
363
- L: 130,
402
+ L: 185,
364
403
  S: this,
365
404
  C: (f, a) => f(...a)
366
405
  });
@@ -380,11 +419,11 @@ var EdgeWsConnection = class extends Resource {
380
419
  if (err instanceof Error && err.message.includes("WebSocket is closed before the connection is established.")) {
381
420
  return;
382
421
  }
383
- log.warn("Error closing websocket", {
422
+ log.warn("error closing websocket", {
384
423
  err
385
424
  }, {
386
425
  F: __dxlog_file3,
387
- L: 148,
426
+ L: 203,
388
427
  S: this,
389
428
  C: (f, a) => f(...a)
390
429
  });
@@ -393,7 +432,7 @@ var EdgeWsConnection = class extends Resource {
393
432
  _scheduleHeartbeats() {
394
433
  invariant3(this._ws, void 0, {
395
434
  F: __dxlog_file3,
396
- L: 153,
435
+ L: 208,
397
436
  S: this,
398
437
  A: [
399
438
  "this._ws",
@@ -401,8 +440,10 @@ var EdgeWsConnection = class extends Resource {
401
440
  ]
402
441
  });
403
442
  scheduleTaskInterval(this._ctx, async () => {
443
+ this._pingTimestamp = Date.now();
404
444
  this._ws?.send("__ping__");
405
445
  }, SIGNAL_KEEPALIVE_INTERVAL);
446
+ this._pingTimestamp = Date.now();
406
447
  this._ws.send("__ping__");
407
448
  this._rescheduleHeartbeatTimeout();
408
449
  }
@@ -413,7 +454,7 @@ var EdgeWsConnection = class extends Resource {
413
454
  void this._inactivityTimeoutCtx?.dispose();
414
455
  this._inactivityTimeoutCtx = new Context(void 0, {
415
456
  F: __dxlog_file3,
416
- L: 172
457
+ L: 229
417
458
  });
418
459
  scheduleTask(this._inactivityTimeoutCtx, () => {
419
460
  if (this.isOpen) {
@@ -422,7 +463,7 @@ var EdgeWsConnection = class extends Resource {
422
463
  lastReceivedMessageTimestamp: this._lastReceivedMessageTimestamp
423
464
  }, {
424
465
  F: __dxlog_file3,
425
- L: 178,
466
+ L: 235,
426
467
  S: this,
427
468
  C: (f, a) => f(...a)
428
469
  });
@@ -433,8 +474,46 @@ var EdgeWsConnection = class extends Resource {
433
474
  }
434
475
  }, SIGNAL_KEEPALIVE_TIMEOUT);
435
476
  }
436
- constructor(_identity, _connectionInfo, _callbacks) {
437
- super(), _define_property(this, "_identity", void 0), _define_property(this, "_connectionInfo", void 0), _define_property(this, "_callbacks", void 0), _define_property(this, "_inactivityTimeoutCtx", void 0), _define_property(this, "_ws", void 0), _define_property(this, "_wsMuxer", void 0), _define_property(this, "_lastReceivedMessageTimestamp", void 0), this._identity = _identity, this._connectionInfo = _connectionInfo, this._callbacks = _callbacks, this._lastReceivedMessageTimestamp = Date.now();
477
+ _recordBytes(sent, received) {
478
+ const now = Date.now();
479
+ const currentSecond = Math.floor(now / 1e3) * 1e3;
480
+ const existingSample = this._bytesSamples.find((s) => Math.floor(s.timestamp / 1e3) * 1e3 === currentSecond);
481
+ if (existingSample) {
482
+ existingSample.sent += sent;
483
+ existingSample.received += received;
484
+ } else {
485
+ this._bytesSamples.push({
486
+ timestamp: now,
487
+ sent,
488
+ received
489
+ });
490
+ }
491
+ }
492
+ _scheduleRateCalculation() {
493
+ scheduleTaskInterval(this._ctx, async () => {
494
+ this._calculateRates();
495
+ }, this._rateUpdateInterval);
496
+ this._calculateRates();
497
+ }
498
+ _calculateRates() {
499
+ const now = Date.now();
500
+ const cutoff = now - this._rateWindow;
501
+ this._bytesSamples = this._bytesSamples.filter((s) => s.timestamp > cutoff);
502
+ if (this._bytesSamples.length === 0) {
503
+ this._uploadRate = 0;
504
+ this._downloadRate = 0;
505
+ return;
506
+ }
507
+ let totalSent = 0;
508
+ let totalReceived = 0;
509
+ const oldestTimestamp = Math.min(...this._bytesSamples.map((s) => s.timestamp));
510
+ const timeSpan = (now - oldestTimestamp) / 1e3;
511
+ for (const sample of this._bytesSamples) {
512
+ totalSent += sample.sent;
513
+ totalReceived += sample.received;
514
+ }
515
+ this._uploadRate = timeSpan > 0 ? Math.round(totalSent / timeSpan) : 0;
516
+ this._downloadRate = timeSpan > 0 ? Math.round(totalReceived / timeSpan) : 0;
438
517
  }
439
518
  };
440
519
  _ts_decorate([
@@ -462,19 +541,6 @@ var getEdgeUrlWithProtocol = (baseUrl, protocol2) => {
462
541
  };
463
542
 
464
543
  // src/edge-client.ts
465
- function _define_property2(obj, key, value) {
466
- if (key in obj) {
467
- Object.defineProperty(obj, key, {
468
- value,
469
- enumerable: true,
470
- configurable: true,
471
- writable: true
472
- });
473
- } else {
474
- obj[key] = value;
475
- }
476
- return obj;
477
- }
478
544
  function _ts_decorate2(decorators, target, key, desc) {
479
545
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
480
546
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -483,7 +549,26 @@ function _ts_decorate2(decorators, target, key, desc) {
483
549
  }
484
550
  var __dxlog_file4 = "/__w/dxos/dxos/packages/core/mesh/edge-client/src/edge-client.ts";
485
551
  var DEFAULT_TIMEOUT = 1e4;
552
+ var STATUS_REFRESH_INTERVAL = 1e3;
486
553
  var EdgeClient = class extends Resource2 {
554
+ _identity;
555
+ _config;
556
+ statusChanged = new Event();
557
+ _persistentLifecycle = new PersistentLifecycle({
558
+ start: async () => this._connect(),
559
+ stop: async (state) => this._disconnect(state)
560
+ });
561
+ _messageListeners = /* @__PURE__ */ new Set();
562
+ _reconnectListeners = /* @__PURE__ */ new Set();
563
+ _baseWsUrl;
564
+ _baseHttpUrl;
565
+ _currentConnection = void 0;
566
+ _ready = new Trigger();
567
+ constructor(_identity, _config) {
568
+ super(), this._identity = _identity, this._config = _config;
569
+ this._baseWsUrl = getEdgeUrlWithProtocol(_config.socketEndpoint, "ws");
570
+ this._baseHttpUrl = getEdgeUrlWithProtocol(_config.socketEndpoint, "http");
571
+ }
487
572
  get info() {
488
573
  return {
489
574
  open: this.isOpen,
@@ -493,7 +578,15 @@ var EdgeClient = class extends Resource2 {
493
578
  };
494
579
  }
495
580
  get status() {
496
- return Boolean(this._currentConnection) && this._ready.state === TriggerState.RESOLVED ? EdgeStatus.CONNECTED : EdgeStatus.NOT_CONNECTED;
581
+ return {
582
+ state: Boolean(this._currentConnection) && this._ready.state === TriggerState.RESOLVED ? EdgeStatus.ConnectionState.CONNECTED : EdgeStatus.ConnectionState.NOT_CONNECTED,
583
+ uptime: this._currentConnection?.uptime ?? 0,
584
+ rtt: this._currentConnection?.rtt ?? 0,
585
+ rateBytesUp: this._currentConnection?.uploadRate ?? 0,
586
+ rateBytesDown: this._currentConnection?.downloadRate ?? 0,
587
+ messagesSent: this._currentConnection?.messagesSent ?? 0,
588
+ messagesReceived: this._currentConnection?.messagesReceived ?? 0
589
+ };
497
590
  }
498
591
  get identityKey() {
499
592
  return this._identity.identityKey;
@@ -508,7 +601,7 @@ var EdgeClient = class extends Resource2 {
508
601
  oldIdentity: this._identity
509
602
  }, {
510
603
  F: __dxlog_file4,
511
- L: 99,
604
+ L: 118,
512
605
  S: this,
513
606
  C: (f, a) => f(...a)
514
607
  });
@@ -525,7 +618,7 @@ var EdgeClient = class extends Resource2 {
525
618
  if (this._ready.state !== TriggerState.RESOLVED) {
526
619
  log2("waiting for websocket", void 0, {
527
620
  F: __dxlog_file4,
528
- L: 112,
621
+ L: 131,
529
622
  S: this,
530
623
  C: (f, a) => f(...a)
531
624
  });
@@ -555,7 +648,7 @@ var EdgeClient = class extends Resource2 {
555
648
  } catch (error) {
556
649
  log2.catch(error, void 0, {
557
650
  F: __dxlog_file4,
558
- L: 145,
651
+ L: 164,
559
652
  S: this,
560
653
  C: (f, a) => f(...a)
561
654
  });
@@ -573,7 +666,7 @@ var EdgeClient = class extends Resource2 {
573
666
  info: this.info
574
667
  }, {
575
668
  F: __dxlog_file4,
576
- L: 158,
669
+ L: 177,
577
670
  S: this,
578
671
  C: (f, a) => f(...a)
579
672
  });
@@ -582,11 +675,17 @@ var EdgeClient = class extends Resource2 {
582
675
  err
583
676
  }, {
584
677
  F: __dxlog_file4,
585
- L: 160,
678
+ L: 179,
586
679
  S: this,
587
680
  C: (f, a) => f(...a)
588
681
  });
589
682
  });
683
+ scheduleTaskInterval2(this._ctx, async () => {
684
+ if (!this._currentConnection) {
685
+ return;
686
+ }
687
+ this.statusChanged.emit(this.status);
688
+ }, STATUS_REFRESH_INTERVAL);
590
689
  }
591
690
  /**
592
691
  * Close connection and free resources.
@@ -596,7 +695,7 @@ var EdgeClient = class extends Resource2 {
596
695
  peerKey: this._identity.peerKey
597
696
  }, {
598
697
  F: __dxlog_file4,
599
- L: 168,
698
+ L: 199,
600
699
  S: this,
601
700
  C: (f, a) => f(...a)
602
701
  });
@@ -613,7 +712,7 @@ var EdgeClient = class extends Resource2 {
613
712
  if (this._identity !== identity) {
614
713
  log2("identity changed during auth header request", void 0, {
615
714
  F: __dxlog_file4,
616
- L: 182,
715
+ L: 213,
617
716
  S: this,
618
717
  C: (f, a) => f(...a)
619
718
  });
@@ -626,7 +725,7 @@ var EdgeClient = class extends Resource2 {
626
725
  protocolHeader
627
726
  }, {
628
727
  F: __dxlog_file4,
629
- L: 188,
728
+ L: 219,
630
729
  S: this,
631
730
  C: (f, a) => f(...a)
632
731
  });
@@ -641,7 +740,7 @@ var EdgeClient = class extends Resource2 {
641
740
  } else {
642
741
  log2.verbose("connected callback ignored, because connection is not active", void 0, {
643
742
  F: __dxlog_file4,
644
- L: 198,
743
+ L: 229,
645
744
  S: this,
646
745
  C: (f, a) => f(...a)
647
746
  });
@@ -654,7 +753,7 @@ var EdgeClient = class extends Resource2 {
654
753
  } else {
655
754
  log2.verbose("restart requested by inactive connection", void 0, {
656
755
  F: __dxlog_file4,
657
- L: 206,
756
+ L: 237,
658
757
  S: this,
659
758
  C: (f, a) => f(...a)
660
759
  });
@@ -670,7 +769,7 @@ var EdgeClient = class extends Resource2 {
670
769
  type: message.payload?.typeUrl
671
770
  }, {
672
771
  F: __dxlog_file4,
673
- L: 214,
772
+ L: 245,
674
773
  S: this,
675
774
  C: (f, a) => f(...a)
676
775
  });
@@ -707,7 +806,7 @@ var EdgeClient = class extends Resource2 {
707
806
  err
708
807
  }, {
709
808
  F: __dxlog_file4,
710
- L: 249,
809
+ L: 280,
711
810
  S: this,
712
811
  C: (f, a) => f(...a)
713
812
  });
@@ -724,7 +823,7 @@ var EdgeClient = class extends Resource2 {
724
823
  payload: protocol.getPayloadType(message)
725
824
  }, {
726
825
  F: __dxlog_file4,
727
- L: 259,
826
+ L: 290,
728
827
  S: this,
729
828
  C: (f, a) => f(...a)
730
829
  });
@@ -745,21 +844,14 @@ var EdgeClient = class extends Resource2 {
745
844
  statusText: response.statusText
746
845
  }, {
747
846
  F: __dxlog_file4,
748
- L: 271,
847
+ L: 302,
749
848
  S: this,
750
849
  C: (f, a) => f(...a)
751
850
  });
752
851
  return void 0;
753
852
  }
754
853
  }
755
- constructor(_identity, _config) {
756
- super(), _define_property2(this, "_identity", void 0), _define_property2(this, "_config", void 0), _define_property2(this, "statusChanged", void 0), _define_property2(this, "_persistentLifecycle", void 0), _define_property2(this, "_messageListeners", void 0), _define_property2(this, "_reconnectListeners", void 0), _define_property2(this, "_baseWsUrl", void 0), _define_property2(this, "_baseHttpUrl", void 0), _define_property2(this, "_currentConnection", void 0), _define_property2(this, "_ready", void 0), _define_property2(this, "_isActive", void 0), this._identity = _identity, this._config = _config, this.statusChanged = new Event(), this._persistentLifecycle = new PersistentLifecycle({
757
- start: async () => this._connect(),
758
- stop: async (state) => this._disconnect(state)
759
- }), this._messageListeners = /* @__PURE__ */ new Set(), this._reconnectListeners = /* @__PURE__ */ new Set(), this._currentConnection = void 0, this._ready = new Trigger(), this._isActive = (connection) => connection === this._currentConnection;
760
- this._baseWsUrl = getEdgeUrlWithProtocol(_config.socketEndpoint, "ws");
761
- this._baseHttpUrl = getEdgeUrlWithProtocol(_config.socketEndpoint, "http");
762
- }
854
+ _isActive = (connection) => connection === this._currentConnection;
763
855
  };
764
856
  _ts_decorate2([
765
857
  logInfo2
@@ -770,44 +862,37 @@ var encodePresentationWsAuthHeader = (encodedPresentation) => {
770
862
  };
771
863
 
772
864
  // src/edge-http-client.ts
773
- import { FetchHttpClient, HttpClient } from "@effect/platform";
774
- import { Effect as Effect2, pipe } from "effect";
865
+ import * as FetchHttpClient from "@effect/platform/FetchHttpClient";
866
+ import * as HttpClient from "@effect/platform/HttpClient";
867
+ import * as Effect2 from "effect/Effect";
868
+ import * as Function from "effect/Function";
775
869
  import { sleep } from "@dxos/async";
776
870
  import { Context as Context3 } from "@dxos/context";
871
+ import { invariant as invariant4 } from "@dxos/invariant";
777
872
  import { log as log4 } from "@dxos/log";
778
873
  import { EdgeAuthChallengeError, EdgeCallFailedError } from "@dxos/protocols";
779
874
  import { createUrl } from "@dxos/util";
780
875
 
781
876
  // src/http-client.ts
782
- import { Context as Context2, Duration, Effect, Layer, Schedule } from "effect";
877
+ import * as Context2 from "effect/Context";
878
+ import * as Duration from "effect/Duration";
879
+ import * as Effect from "effect/Effect";
880
+ import * as Layer from "effect/Layer";
881
+ import * as Schedule from "effect/Schedule";
783
882
  import { log as log3 } from "@dxos/log";
784
- function _define_property3(obj, key, value) {
785
- if (key in obj) {
786
- Object.defineProperty(obj, key, {
787
- value,
788
- enumerable: true,
789
- configurable: true,
790
- writable: true
791
- });
792
- } else {
793
- obj[key] = value;
794
- }
795
- return obj;
796
- }
797
883
  var __dxlog_file5 = "/__w/dxos/dxos/packages/core/mesh/edge-client/src/http-client.ts";
798
- var _Context_Tag;
799
- var HttpConfig = class extends (_Context_Tag = Context2.Tag("HttpConfig")()) {
884
+ var HttpConfig = class _HttpConfig extends Context2.Tag("HttpConfig")() {
885
+ static default = Layer.succeed(_HttpConfig, {
886
+ timeout: Duration.millis(1e3),
887
+ retryTimes: 3,
888
+ retryBaseDelay: Duration.millis(1e3)
889
+ });
800
890
  };
801
- _define_property3(HttpConfig, "default", Layer.succeed(HttpConfig, {
802
- timeout: Duration.millis(1e3),
803
- retryTimes: 3,
804
- retryBaseDelay: Duration.millis(1e3)
805
- }));
806
- var withRetry = (effect, { timeout = Duration.millis(1e3), retryBaseDelay = Duration.millis(1e3), retryTimes = 3 } = {}) => {
891
+ var withRetry = (effect, { timeout: timeout2 = Duration.millis(1e3), retryBaseDelay = Duration.millis(1e3), retryTimes = 3 } = {}) => {
807
892
  return effect.pipe(Effect.flatMap((res) => (
808
893
  // Treat 500 errors as retryable?
809
894
  res.status === 500 ? Effect.fail(new Error(res.status.toString())) : res.json
810
- )), Effect.timeout(timeout), Effect.retry({
895
+ )), Effect.timeout(timeout2), Effect.retry({
811
896
  schedule: Schedule.exponential(retryBaseDelay).pipe(Schedule.jittered),
812
897
  times: retryTimes
813
898
  }));
@@ -820,7 +905,7 @@ var withLogging = (effect) => effect.pipe(Effect.tap((res) => log3.info("respons
820
905
  status: res.status
821
906
  }, {
822
907
  F: __dxlog_file5,
823
- L: 58,
908
+ L: 64,
824
909
  S: void 0,
825
910
  C: (f, a) => f(...a)
826
911
  })));
@@ -830,25 +915,29 @@ var encodeAuthHeader = (challenge) => {
830
915
  };
831
916
 
832
917
  // src/edge-http-client.ts
833
- function _define_property4(obj, key, value) {
834
- if (key in obj) {
835
- Object.defineProperty(obj, key, {
836
- value,
837
- enumerable: true,
838
- configurable: true,
839
- writable: true
840
- });
841
- } else {
842
- obj[key] = value;
843
- }
844
- return obj;
845
- }
846
918
  var __dxlog_file6 = "/__w/dxos/dxos/packages/core/mesh/edge-client/src/edge-http-client.ts";
847
919
  var DEFAULT_RETRY_TIMEOUT = 1500;
848
920
  var DEFAULT_RETRY_JITTER = 500;
849
921
  var DEFAULT_MAX_RETRIES_COUNT = 3;
850
922
  var WARNING_BODY_SIZE = 10 * 1024 * 1024;
851
923
  var EdgeHttpClient = class {
924
+ _baseUrl;
925
+ _edgeIdentity;
926
+ /**
927
+ * Auth header is cached until receiving the next 401 from EDGE, at which point it gets refreshed.
928
+ */
929
+ _authHeader;
930
+ constructor(baseUrl) {
931
+ this._baseUrl = getEdgeUrlWithProtocol(baseUrl, "http");
932
+ log4("created", {
933
+ url: this._baseUrl
934
+ }, {
935
+ F: __dxlog_file6,
936
+ L: 101,
937
+ S: this,
938
+ C: (f, a) => f(...a)
939
+ });
940
+ }
852
941
  get baseUrl() {
853
942
  return this._baseUrl;
854
943
  }
@@ -1067,74 +1156,90 @@ var EdgeHttpClient = class {
1067
1156
  // Internal
1068
1157
  //
1069
1158
  async _fetch(url, args) {
1070
- return pipe(HttpClient.get(url), withLogging, withRetryConfig, Effect2.provide(FetchHttpClient.layer), Effect2.provide(HttpConfig.default), Effect2.withSpan("EdgeHttpClient"), Effect2.runPromise);
1159
+ return Function.pipe(HttpClient.get(url), withLogging, withRetryConfig, Effect2.provide(FetchHttpClient.layer), Effect2.provide(HttpConfig.default), Effect2.withSpan("EdgeHttpClient"), Effect2.runPromise);
1071
1160
  }
1072
1161
  // TODO(burdon): Refactor with effect (see edge-http-client.test.ts).
1073
1162
  async _call(url, args) {
1074
1163
  const shouldRetry = createRetryHandler(args);
1075
- const requestContext = args.context ?? new Context3(void 0, {
1164
+ const requestContext = args.context ?? Context3.default(void 0, {
1076
1165
  F: __dxlog_file6,
1077
- L: 389
1166
+ L: 393
1078
1167
  });
1079
1168
  log4("fetch", {
1080
1169
  url,
1081
1170
  request: args.body
1082
1171
  }, {
1083
1172
  F: __dxlog_file6,
1084
- L: 390,
1173
+ L: 394,
1085
1174
  S: this,
1086
1175
  C: (f, a) => f(...a)
1087
1176
  });
1088
1177
  let handledAuth = false;
1089
1178
  while (true) {
1090
1179
  let processingError = void 0;
1091
- let retryAfterHeaderValue = Number.NaN;
1092
1180
  try {
1093
1181
  const request = createRequest(args, this._authHeader);
1094
1182
  const response = await fetch(url, request);
1095
- retryAfterHeaderValue = Number(response.headers.get("Retry-After"));
1183
+ const body = response.headers.get("Content-Type") === "application/json" ? await response.clone().json() : void 0;
1096
1184
  if (response.ok) {
1097
- const body = await response.json();
1098
1185
  if (args.rawResponse) {
1099
1186
  return body;
1100
1187
  }
1188
+ invariant4(body, "Expected body to be present", {
1189
+ F: __dxlog_file6,
1190
+ L: 409,
1191
+ S: this,
1192
+ A: [
1193
+ "body",
1194
+ "'Expected body to be present'"
1195
+ ]
1196
+ });
1101
1197
  if (!("success" in body)) {
1102
1198
  return body;
1103
1199
  }
1104
1200
  if (body.success) {
1105
1201
  return body.data;
1106
1202
  }
1107
- log4.warn("unsuccessful edge response", {
1108
- url,
1109
- body
1110
- }, {
1111
- F: __dxlog_file6,
1112
- L: 415,
1113
- S: this,
1114
- C: (f, a) => f(...a)
1115
- });
1116
- if (body.errorData?.type === "auth_challenge" && typeof body.errorData?.challenge === "string") {
1117
- processingError = new EdgeAuthChallengeError(body.errorData.challenge, body.errorData);
1118
- } else if (body.errorData) {
1119
- processingError = EdgeCallFailedError.fromUnsuccessfulResponse(response, body);
1120
- }
1121
1203
  } else if (response.status === 401 && !handledAuth) {
1122
1204
  this._authHeader = await this._handleUnauthorized(response);
1123
1205
  handledAuth = true;
1124
1206
  continue;
1207
+ }
1208
+ invariant4(!body?.success, "Expected body to not be a failure response or undefined.", {
1209
+ F: __dxlog_file6,
1210
+ L: 422,
1211
+ S: this,
1212
+ A: [
1213
+ "!body?.success",
1214
+ "'Expected body to not be a failure response or undefined.'"
1215
+ ]
1216
+ });
1217
+ if (body?.errorData?.type === "auth_challenge" && typeof body?.errorData?.challenge === "string") {
1218
+ processingError = new EdgeAuthChallengeError(body.errorData.challenge, body.errorData);
1219
+ } else if (body?.success === false) {
1220
+ processingError = EdgeCallFailedError.fromUnsuccessfulResponse(response, body);
1125
1221
  } else {
1222
+ invariant4(!response.ok, "Expected response to not be ok.", {
1223
+ F: __dxlog_file6,
1224
+ L: 429,
1225
+ S: this,
1226
+ A: [
1227
+ "!response.ok",
1228
+ "'Expected response to not be ok.'"
1229
+ ]
1230
+ });
1126
1231
  processingError = await EdgeCallFailedError.fromHttpFailure(response);
1127
1232
  }
1128
1233
  } catch (error) {
1129
1234
  processingError = EdgeCallFailedError.fromProcessingFailureCause(error);
1130
1235
  }
1131
- if (processingError?.isRetryable && await shouldRetry(requestContext, retryAfterHeaderValue)) {
1236
+ if (processingError?.isRetryable && await shouldRetry(requestContext, processingError.retryAfterMs)) {
1132
1237
  log4("retrying edge request", {
1133
1238
  url,
1134
1239
  processingError
1135
1240
  }, {
1136
1241
  F: __dxlog_file6,
1137
- L: 433,
1242
+ L: 437,
1138
1243
  S: this,
1139
1244
  C: (f, a) => f(...a)
1140
1245
  });
@@ -1147,7 +1252,7 @@ var EdgeHttpClient = class {
1147
1252
  if (!this._edgeIdentity) {
1148
1253
  log4.warn("unauthorized response received before identity was set", void 0, {
1149
1254
  F: __dxlog_file6,
1150
- L: 442,
1255
+ L: 446,
1151
1256
  S: this,
1152
1257
  C: (f, a) => f(...a)
1153
1258
  });
@@ -1156,20 +1261,6 @@ var EdgeHttpClient = class {
1156
1261
  const challenge = await handleAuthChallenge(response, this._edgeIdentity);
1157
1262
  return encodeAuthHeader(challenge);
1158
1263
  }
1159
- constructor(baseUrl) {
1160
- _define_property4(this, "_baseUrl", void 0);
1161
- _define_property4(this, "_edgeIdentity", void 0);
1162
- _define_property4(this, "_authHeader", void 0);
1163
- this._baseUrl = getEdgeUrlWithProtocol(baseUrl, "http");
1164
- log4("created", {
1165
- url: this._baseUrl
1166
- }, {
1167
- F: __dxlog_file6,
1168
- L: 97,
1169
- S: this,
1170
- C: (f, a) => f(...a)
1171
- });
1172
- }
1173
1264
  };
1174
1265
  var createRequest = ({ method, body, json = true }, authHeader) => {
1175
1266
  let requestBody;
@@ -1185,7 +1276,7 @@ var createRequest = ({ method, body, json = true }, authHeader) => {
1185
1276
  bodySize: requestBody.length
1186
1277
  }, {
1187
1278
  F: __dxlog_file6,
1188
- L: 466,
1279
+ L: 470,
1189
1280
  S: void 0,
1190
1281
  C: (f, a) => f(...a)
1191
1282
  });
@@ -1199,14 +1290,14 @@ var createRequest = ({ method, body, json = true }, authHeader) => {
1199
1290
  headers
1200
1291
  };
1201
1292
  };
1202
- var createRetryHandler = ({ retry }) => {
1203
- if (!retry || retry.count < 1) {
1293
+ var createRetryHandler = ({ retry: retry2 }) => {
1294
+ if (!retry2 || retry2.count < 1) {
1204
1295
  return async () => false;
1205
1296
  }
1206
1297
  let retries = 0;
1207
- const maxRetries = retry.count ?? DEFAULT_MAX_RETRIES_COUNT;
1208
- const baseTimeout = retry.timeout ?? DEFAULT_RETRY_TIMEOUT;
1209
- const jitter = retry.jitter ?? DEFAULT_RETRY_JITTER;
1298
+ const maxRetries = retry2.count ?? DEFAULT_MAX_RETRIES_COUNT;
1299
+ const baseTimeout = retry2.timeout ?? DEFAULT_RETRY_TIMEOUT;
1300
+ const jitter = retry2.jitter ?? DEFAULT_RETRY_JITTER;
1210
1301
  return async (ctx, retryAfter) => {
1211
1302
  if (++retries > maxRetries || ctx.disposed) {
1212
1303
  return false;
@@ -1214,8 +1305,8 @@ var createRetryHandler = ({ retry }) => {
1214
1305
  if (retryAfter) {
1215
1306
  await sleep(retryAfter);
1216
1307
  } else {
1217
- const timeout = baseTimeout + Math.random() * jitter;
1218
- await sleep(timeout);
1308
+ const timeout2 = baseTimeout + Math.random() * jitter;
1309
+ await sleep(timeout2);
1219
1310
  }
1220
1311
  return true;
1221
1312
  };