@dxos/edge-client 0.8.4-main.f9ba587 → 0.8.4-main.fffef41

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 (42) hide show
  1. package/dist/lib/browser/{chunk-LMP5TVOP.mjs → chunk-VESGVCLQ.mjs} +8 -4
  2. package/dist/lib/browser/{chunk-LMP5TVOP.mjs.map → chunk-VESGVCLQ.mjs.map} +3 -3
  3. package/dist/lib/browser/edge-ws-muxer.mjs +1 -1
  4. package/dist/lib/browser/index.mjs +557 -284
  5. package/dist/lib/browser/index.mjs.map +4 -4
  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-X7J46ISZ.mjs → chunk-JTBFRYNM.mjs} +8 -4
  10. package/dist/lib/node-esm/{chunk-X7J46ISZ.mjs.map → chunk-JTBFRYNM.mjs.map} +3 -3
  11. package/dist/lib/node-esm/edge-ws-muxer.mjs +1 -1
  12. package/dist/lib/node-esm/index.mjs +557 -284
  13. package/dist/lib/node-esm/index.mjs.map +4 -4
  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 +15 -15
  18. package/dist/types/src/edge-client.d.ts.map +1 -1
  19. package/dist/types/src/edge-http-client.d.ts +30 -3
  20. package/dist/types/src/edge-http-client.d.ts.map +1 -1
  21. package/dist/types/src/edge-ws-connection.d.ts +20 -0
  22. package/dist/types/src/edge-ws-connection.d.ts.map +1 -1
  23. package/dist/types/src/edge-ws-muxer.d.ts.map +1 -1
  24. package/dist/types/src/http-client.d.ts +10 -7
  25. package/dist/types/src/http-client.d.ts.map +1 -1
  26. package/dist/types/src/index.d.ts +4 -3
  27. package/dist/types/src/index.d.ts.map +1 -1
  28. package/dist/types/src/testing/test-utils.d.ts +1 -1
  29. package/dist/types/src/testing/test-utils.d.ts.map +1 -1
  30. package/dist/types/tsconfig.tsbuildinfo +1 -1
  31. package/package.json +18 -15
  32. package/src/edge-client.test.ts +4 -4
  33. package/src/edge-client.ts +73 -42
  34. package/src/edge-http-client.test.ts +1 -1
  35. package/src/edge-http-client.ts +194 -35
  36. package/src/edge-ws-connection.ts +129 -8
  37. package/src/edge-ws-muxer.ts +1 -1
  38. package/src/http-client.test.ts +8 -6
  39. package/src/http-client.ts +18 -8
  40. package/src/index.ts +4 -3
  41. package/src/testing/test-utils.ts +4 -4
  42. package/src/websocket.test.ts +1 -1
@@ -6,24 +6,135 @@ import {
6
6
  getTypename,
7
7
  protocol,
8
8
  toUint8Array
9
- } from "./chunk-LMP5TVOP.mjs";
9
+ } from "./chunk-VESGVCLQ.mjs";
10
10
 
11
11
  // src/index.ts
12
12
  export * from "@dxos/protocols/buf/dxos/edge/messenger_pb";
13
13
 
14
+ // src/auth.ts
15
+ import { createCredential, signPresentation } from "@dxos/credentials";
16
+ import { invariant } from "@dxos/invariant";
17
+ import { Keyring } from "@dxos/keyring";
18
+ import { PublicKey } from "@dxos/keys";
19
+ var __dxlog_file = "/__w/dxos/dxos/packages/core/mesh/edge-client/src/auth.ts";
20
+ var createDeviceEdgeIdentity = async (signer, key) => {
21
+ return {
22
+ identityKey: key.toHex(),
23
+ peerKey: key.toHex(),
24
+ presentCredentials: async ({ challenge }) => {
25
+ return signPresentation({
26
+ presentation: {
27
+ credentials: [
28
+ // Verifier requires at least one credential in the presentation to establish the subject.
29
+ await createCredential({
30
+ assertion: {
31
+ "@type": "dxos.halo.credentials.Auth"
32
+ },
33
+ issuer: key,
34
+ subject: key,
35
+ signer
36
+ })
37
+ ]
38
+ },
39
+ signer,
40
+ signerKey: key,
41
+ nonce: challenge
42
+ });
43
+ }
44
+ };
45
+ };
46
+ var createChainEdgeIdentity = async (signer, identityKey, peerKey, chain, credentials) => {
47
+ const credentialsToSign = credentials.length > 0 ? credentials : [
48
+ await createCredential({
49
+ assertion: {
50
+ "@type": "dxos.halo.credentials.Auth"
51
+ },
52
+ issuer: identityKey,
53
+ subject: identityKey,
54
+ signer,
55
+ chain,
56
+ signingKey: peerKey
57
+ })
58
+ ];
59
+ return {
60
+ identityKey: identityKey.toHex(),
61
+ peerKey: peerKey.toHex(),
62
+ presentCredentials: async ({ challenge }) => {
63
+ invariant(chain, void 0, {
64
+ F: __dxlog_file,
65
+ L: 75,
66
+ S: void 0,
67
+ A: [
68
+ "chain",
69
+ ""
70
+ ]
71
+ });
72
+ return signPresentation({
73
+ presentation: {
74
+ credentials: credentialsToSign
75
+ },
76
+ signer,
77
+ nonce: challenge,
78
+ signerKey: peerKey,
79
+ chain
80
+ });
81
+ }
82
+ };
83
+ };
84
+ var createEphemeralEdgeIdentity = async () => {
85
+ const keyring = new Keyring();
86
+ const key = await keyring.createKey();
87
+ return createDeviceEdgeIdentity(keyring, key);
88
+ };
89
+ var createTestHaloEdgeIdentity = async (signer, identityKey, deviceKey) => {
90
+ const deviceAdmission = await createCredential({
91
+ assertion: {
92
+ "@type": "dxos.halo.credentials.AuthorizedDevice",
93
+ deviceKey,
94
+ identityKey
95
+ },
96
+ issuer: identityKey,
97
+ subject: deviceKey,
98
+ signer
99
+ });
100
+ return createChainEdgeIdentity(signer, identityKey, deviceKey, {
101
+ credential: deviceAdmission
102
+ }, [
103
+ await createCredential({
104
+ assertion: {
105
+ "@type": "dxos.halo.credentials.Auth"
106
+ },
107
+ issuer: identityKey,
108
+ subject: identityKey,
109
+ signer
110
+ })
111
+ ]);
112
+ };
113
+ var createStubEdgeIdentity = () => {
114
+ const identityKey = PublicKey.random();
115
+ const deviceKey = PublicKey.random();
116
+ return {
117
+ identityKey: identityKey.toHex(),
118
+ peerKey: deviceKey.toHex(),
119
+ presentCredentials: async () => {
120
+ throw new Error("Stub identity does not support authentication.");
121
+ }
122
+ };
123
+ };
124
+
14
125
  // src/edge-client.ts
15
- import { Trigger, scheduleMicroTask, TriggerState, PersistentLifecycle, Event } from "@dxos/async";
126
+ import { Event, PersistentLifecycle, Trigger, TriggerState, scheduleMicroTask, scheduleTaskInterval as scheduleTaskInterval2 } from "@dxos/async";
16
127
  import { Resource as Resource2 } from "@dxos/context";
17
128
  import { log as log2, logInfo as logInfo2 } from "@dxos/log";
18
129
  import { EdgeStatus } from "@dxos/protocols/proto/dxos/client/services";
19
130
 
20
131
  // src/edge-identity.ts
21
- import { invariant } from "@dxos/invariant";
132
+ import { invariant as invariant2 } from "@dxos/invariant";
22
133
  import { schema } from "@dxos/protocols/proto";
23
- var __dxlog_file = "/__w/dxos/dxos/packages/core/mesh/edge-client/src/edge-identity.ts";
134
+ var __dxlog_file2 = "/__w/dxos/dxos/packages/core/mesh/edge-client/src/edge-identity.ts";
24
135
  var handleAuthChallenge = async (failedResponse, identity) => {
25
- invariant(failedResponse.status === 401, void 0, {
26
- F: __dxlog_file,
136
+ invariant2(failedResponse.status === 401, void 0, {
137
+ F: __dxlog_file2,
27
138
  L: 21,
28
139
  S: void 0,
29
140
  A: [
@@ -32,8 +143,8 @@ var handleAuthChallenge = async (failedResponse, identity) => {
32
143
  ]
33
144
  });
34
145
  const headerValue = failedResponse.headers.get("Www-Authenticate");
35
- invariant(headerValue?.startsWith("VerifiablePresentation challenge="), void 0, {
36
- F: __dxlog_file,
146
+ invariant2(headerValue?.startsWith("VerifiablePresentation challenge="), void 0, {
147
+ F: __dxlog_file2,
37
148
  L: 24,
38
149
  S: void 0,
39
150
  A: [
@@ -42,8 +153,8 @@ var handleAuthChallenge = async (failedResponse, identity) => {
42
153
  ]
43
154
  });
44
155
  const challenge = headerValue?.slice("VerifiablePresentation challenge=".length);
45
- invariant(challenge, void 0, {
46
- F: __dxlog_file,
156
+ invariant2(challenge, void 0, {
157
+ F: __dxlog_file2,
47
158
  L: 27,
48
159
  S: void 0,
49
160
  A: [
@@ -61,7 +172,7 @@ var handleAuthChallenge = async (failedResponse, identity) => {
61
172
  import WebSocket from "isomorphic-ws";
62
173
  import { scheduleTask, scheduleTaskInterval } from "@dxos/async";
63
174
  import { Context, Resource } from "@dxos/context";
64
- import { invariant as invariant2 } from "@dxos/invariant";
175
+ import { invariant as invariant3 } from "@dxos/invariant";
65
176
  import { log, logInfo } from "@dxos/log";
66
177
  import { EdgeWebsocketProtocol } from "@dxos/protocols";
67
178
  import { buf } from "@dxos/protocols/buf";
@@ -72,10 +183,29 @@ function _ts_decorate(decorators, target, key, desc) {
72
183
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
73
184
  return c > 3 && r && Object.defineProperty(target, key, r), r;
74
185
  }
75
- var __dxlog_file2 = "/__w/dxos/dxos/packages/core/mesh/edge-client/src/edge-ws-connection.ts";
186
+ var __dxlog_file3 = "/__w/dxos/dxos/packages/core/mesh/edge-client/src/edge-ws-connection.ts";
76
187
  var SIGNAL_KEEPALIVE_INTERVAL = 4e3;
77
188
  var SIGNAL_KEEPALIVE_TIMEOUT = 12e3;
78
189
  var EdgeWsConnection = class extends Resource {
190
+ _identity;
191
+ _connectionInfo;
192
+ _callbacks;
193
+ _inactivityTimeoutCtx;
194
+ _ws;
195
+ _wsMuxer;
196
+ _lastReceivedMessageTimestamp = Date.now();
197
+ _openTimestamp;
198
+ // Latency tracking.
199
+ _pingTimestamp;
200
+ _rtt = 0;
201
+ // Rate tracking with sliding window.
202
+ _uploadRate = 0;
203
+ _downloadRate = 0;
204
+ _rateWindow = 1e4;
205
+ _rateUpdateInterval = 1e3;
206
+ _bytesSamples = [];
207
+ _messagesSent = 0;
208
+ _messagesReceived = 0;
79
209
  constructor(_identity, _connectionInfo, _callbacks) {
80
210
  super(), this._identity = _identity, this._connectionInfo = _connectionInfo, this._callbacks = _callbacks;
81
211
  }
@@ -86,19 +216,37 @@ var EdgeWsConnection = class extends Resource {
86
216
  device: this._identity.peerKey
87
217
  };
88
218
  }
219
+ get rtt() {
220
+ return this._rtt;
221
+ }
222
+ get uptime() {
223
+ return this._openTimestamp ? (Date.now() - this._openTimestamp) / 1e3 : 0;
224
+ }
225
+ get uploadRate() {
226
+ return this._uploadRate;
227
+ }
228
+ get downloadRate() {
229
+ return this._downloadRate;
230
+ }
231
+ get messagesSent() {
232
+ return this._messagesSent;
233
+ }
234
+ get messagesReceived() {
235
+ return this._messagesReceived;
236
+ }
89
237
  send(message) {
90
- invariant2(this._ws, void 0, {
91
- F: __dxlog_file2,
92
- L: 52,
238
+ invariant3(this._ws, void 0, {
239
+ F: __dxlog_file3,
240
+ L: 93,
93
241
  S: this,
94
242
  A: [
95
243
  "this._ws",
96
244
  ""
97
245
  ]
98
246
  });
99
- invariant2(this._wsMuxer, void 0, {
100
- F: __dxlog_file2,
101
- L: 53,
247
+ invariant3(this._wsMuxer, void 0, {
248
+ F: __dxlog_file3,
249
+ L: 94,
102
250
  S: this,
103
251
  A: [
104
252
  "this._wsMuxer",
@@ -109,11 +257,12 @@ var EdgeWsConnection = class extends Resource {
109
257
  peerKey: this._identity.peerKey,
110
258
  payload: protocol.getPayloadType(message)
111
259
  }, {
112
- F: __dxlog_file2,
113
- L: 54,
260
+ F: __dxlog_file3,
261
+ L: 95,
114
262
  S: this,
115
263
  C: (f, a) => f(...a)
116
264
  });
265
+ this._messagesSent++;
117
266
  if (this._ws?.protocol.includes(EdgeWebsocketProtocol.V0)) {
118
267
  const binary = buf.toBinary(MessageSchema, message);
119
268
  if (binary.length > CLOUDFLARE_MESSAGE_MAX_BYTES) {
@@ -122,18 +271,21 @@ var EdgeWsConnection = class extends Resource {
122
271
  serviceId: message.serviceId,
123
272
  payload: protocol.getPayloadType(message)
124
273
  }, {
125
- F: __dxlog_file2,
126
- L: 58,
274
+ F: __dxlog_file3,
275
+ L: 100,
127
276
  S: this,
128
277
  C: (f, a) => f(...a)
129
278
  });
130
279
  return;
131
280
  }
281
+ this._recordBytes(binary.byteLength, 0);
132
282
  this._ws.send(binary);
133
283
  } else {
284
+ const binary = buf.toBinary(MessageSchema, message);
285
+ this._recordBytes(binary.byteLength, 0);
134
286
  this._wsMuxer.send(message).catch((e) => log.catch(e, void 0, {
135
- F: __dxlog_file2,
136
- L: 67,
287
+ F: __dxlog_file3,
288
+ L: 113,
137
289
  S: this,
138
290
  C: (f, a) => f(...a)
139
291
  }));
@@ -154,19 +306,21 @@ var EdgeWsConnection = class extends Resource {
154
306
  this._ws.onopen = () => {
155
307
  if (this.isOpen) {
156
308
  log("connected", void 0, {
157
- F: __dxlog_file2,
158
- L: 84,
309
+ F: __dxlog_file3,
310
+ L: 130,
159
311
  S: this,
160
312
  C: (f, a) => f(...a)
161
313
  });
314
+ this._openTimestamp = Date.now();
162
315
  this._callbacks.onConnected();
163
316
  this._scheduleHeartbeats();
317
+ this._scheduleRateCalculation();
164
318
  } else {
165
319
  log.verbose("connected after becoming inactive", {
166
320
  currentIdentity: this._identity
167
321
  }, {
168
- F: __dxlog_file2,
169
- L: 88,
322
+ F: __dxlog_file3,
323
+ L: 136,
170
324
  S: this,
171
325
  C: (f, a) => f(...a)
172
326
  });
@@ -174,12 +328,12 @@ var EdgeWsConnection = class extends Resource {
174
328
  };
175
329
  this._ws.onclose = (event) => {
176
330
  if (this.isOpen) {
177
- log.warn("disconnected while being open", {
331
+ log.warn("server disconnected", {
178
332
  code: event.code,
179
333
  reason: event.reason
180
334
  }, {
181
- F: __dxlog_file2,
182
- L: 93,
335
+ F: __dxlog_file3,
336
+ L: 141,
183
337
  S: this,
184
338
  C: (f, a) => f(...a)
185
339
  });
@@ -193,8 +347,8 @@ var EdgeWsConnection = class extends Resource {
193
347
  error: event.error,
194
348
  info: event.message
195
349
  }, {
196
- F: __dxlog_file2,
197
- L: 100,
350
+ F: __dxlog_file3,
351
+ L: 148,
198
352
  S: this,
199
353
  C: (f, a) => f(...a)
200
354
  });
@@ -203,8 +357,8 @@ var EdgeWsConnection = class extends Resource {
203
357
  log.verbose("error ignored on closed connection", {
204
358
  error: event.error
205
359
  }, {
206
- F: __dxlog_file2,
207
- L: 103,
360
+ F: __dxlog_file3,
361
+ L: 151,
208
362
  S: this,
209
363
  C: (f, a) => f(...a)
210
364
  });
@@ -215,29 +369,36 @@ var EdgeWsConnection = class extends Resource {
215
369
  log.verbose("message ignored on closed connection", {
216
370
  event: event.type
217
371
  }, {
218
- F: __dxlog_file2,
219
- L: 111,
372
+ F: __dxlog_file3,
373
+ L: 159,
220
374
  S: this,
221
375
  C: (f, a) => f(...a)
222
376
  });
223
377
  return;
224
378
  }
379
+ this._lastReceivedMessageTimestamp = Date.now();
225
380
  if (event.data === "__pong__") {
381
+ if (this._pingTimestamp) {
382
+ this._rtt = Date.now() - this._pingTimestamp;
383
+ this._pingTimestamp = void 0;
384
+ }
226
385
  this._rescheduleHeartbeatTimeout();
227
386
  return;
228
387
  }
229
388
  const bytes = await toUint8Array(event.data);
389
+ this._recordBytes(0, bytes.byteLength);
230
390
  if (!this.isOpen) {
231
391
  return;
232
392
  }
393
+ this._messagesReceived++;
233
394
  const message = this._ws?.protocol?.includes(EdgeWebsocketProtocol.V0) ? buf.fromBinary(MessageSchema, bytes) : muxer.receiveData(bytes);
234
395
  if (message) {
235
396
  log("received", {
236
397
  from: message.source,
237
398
  payload: protocol.getPayloadType(message)
238
399
  }, {
239
- F: __dxlog_file2,
240
- L: 128,
400
+ F: __dxlog_file3,
401
+ L: 185,
241
402
  S: this,
242
403
  C: (f, a) => f(...a)
243
404
  });
@@ -257,20 +418,20 @@ var EdgeWsConnection = class extends Resource {
257
418
  if (err instanceof Error && err.message.includes("WebSocket is closed before the connection is established.")) {
258
419
  return;
259
420
  }
260
- log.warn("Error closing websocket", {
421
+ log.warn("error closing websocket", {
261
422
  err
262
423
  }, {
263
- F: __dxlog_file2,
264
- L: 146,
424
+ F: __dxlog_file3,
425
+ L: 203,
265
426
  S: this,
266
427
  C: (f, a) => f(...a)
267
428
  });
268
429
  }
269
430
  }
270
431
  _scheduleHeartbeats() {
271
- invariant2(this._ws, void 0, {
272
- F: __dxlog_file2,
273
- L: 151,
432
+ invariant3(this._ws, void 0, {
433
+ F: __dxlog_file3,
434
+ L: 208,
274
435
  S: this,
275
436
  A: [
276
437
  "this._ws",
@@ -278,8 +439,10 @@ var EdgeWsConnection = class extends Resource {
278
439
  ]
279
440
  });
280
441
  scheduleTaskInterval(this._ctx, async () => {
442
+ this._pingTimestamp = Date.now();
281
443
  this._ws?.send("__ping__");
282
444
  }, SIGNAL_KEEPALIVE_INTERVAL);
445
+ this._pingTimestamp = Date.now();
283
446
  this._ws.send("__ping__");
284
447
  this._rescheduleHeartbeatTimeout();
285
448
  }
@@ -289,21 +452,68 @@ var EdgeWsConnection = class extends Resource {
289
452
  }
290
453
  void this._inactivityTimeoutCtx?.dispose();
291
454
  this._inactivityTimeoutCtx = new Context(void 0, {
292
- F: __dxlog_file2,
293
- L: 170
455
+ F: __dxlog_file3,
456
+ L: 229
294
457
  });
295
458
  scheduleTask(this._inactivityTimeoutCtx, () => {
296
459
  if (this.isOpen) {
297
- log.warn("restart due to inactivity timeout", void 0, {
298
- F: __dxlog_file2,
299
- L: 175,
300
- S: this,
301
- C: (f, a) => f(...a)
302
- });
303
- this._callbacks.onRestartRequired();
460
+ if (Date.now() - this._lastReceivedMessageTimestamp > SIGNAL_KEEPALIVE_TIMEOUT) {
461
+ log.warn("restart due to inactivity timeout", {
462
+ lastReceivedMessageTimestamp: this._lastReceivedMessageTimestamp
463
+ }, {
464
+ F: __dxlog_file3,
465
+ L: 235,
466
+ S: this,
467
+ C: (f, a) => f(...a)
468
+ });
469
+ this._callbacks.onRestartRequired();
470
+ } else {
471
+ this._rescheduleHeartbeatTimeout();
472
+ }
304
473
  }
305
474
  }, SIGNAL_KEEPALIVE_TIMEOUT);
306
475
  }
476
+ _recordBytes(sent, received) {
477
+ const now = Date.now();
478
+ const currentSecond = Math.floor(now / 1e3) * 1e3;
479
+ const existingSample = this._bytesSamples.find((s) => Math.floor(s.timestamp / 1e3) * 1e3 === currentSecond);
480
+ if (existingSample) {
481
+ existingSample.sent += sent;
482
+ existingSample.received += received;
483
+ } else {
484
+ this._bytesSamples.push({
485
+ timestamp: now,
486
+ sent,
487
+ received
488
+ });
489
+ }
490
+ }
491
+ _scheduleRateCalculation() {
492
+ scheduleTaskInterval(this._ctx, async () => {
493
+ this._calculateRates();
494
+ }, this._rateUpdateInterval);
495
+ this._calculateRates();
496
+ }
497
+ _calculateRates() {
498
+ const now = Date.now();
499
+ const cutoff = now - this._rateWindow;
500
+ this._bytesSamples = this._bytesSamples.filter((s) => s.timestamp > cutoff);
501
+ if (this._bytesSamples.length === 0) {
502
+ this._uploadRate = 0;
503
+ this._downloadRate = 0;
504
+ return;
505
+ }
506
+ let totalSent = 0;
507
+ let totalReceived = 0;
508
+ const oldestTimestamp = Math.min(...this._bytesSamples.map((s) => s.timestamp));
509
+ const timeSpan = (now - oldestTimestamp) / 1e3;
510
+ for (const sample of this._bytesSamples) {
511
+ totalSent += sample.sent;
512
+ totalReceived += sample.received;
513
+ }
514
+ this._uploadRate = timeSpan > 0 ? Math.round(totalSent / timeSpan) : 0;
515
+ this._downloadRate = timeSpan > 0 ? Math.round(totalReceived / timeSpan) : 0;
516
+ }
307
517
  };
308
518
  _ts_decorate([
309
519
  logInfo
@@ -336,14 +546,25 @@ function _ts_decorate2(decorators, target, key, desc) {
336
546
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
337
547
  return c > 3 && r && Object.defineProperty(target, key, r), r;
338
548
  }
339
- var __dxlog_file3 = "/__w/dxos/dxos/packages/core/mesh/edge-client/src/edge-client.ts";
549
+ var __dxlog_file4 = "/__w/dxos/dxos/packages/core/mesh/edge-client/src/edge-client.ts";
340
550
  var DEFAULT_TIMEOUT = 1e4;
551
+ var STATUS_REFRESH_INTERVAL = 1e3;
341
552
  var EdgeClient = class extends Resource2 {
553
+ _identity;
554
+ _config;
555
+ statusChanged = new Event();
556
+ _persistentLifecycle = new PersistentLifecycle({
557
+ start: async () => this._connect(),
558
+ stop: async (state) => this._disconnect(state)
559
+ });
560
+ _messageListeners = /* @__PURE__ */ new Set();
561
+ _reconnectListeners = /* @__PURE__ */ new Set();
562
+ _baseWsUrl;
563
+ _baseHttpUrl;
564
+ _currentConnection = void 0;
565
+ _ready = new Trigger();
342
566
  constructor(_identity, _config) {
343
- super(), this._identity = _identity, this._config = _config, this.statusChanged = new Event(), this._persistentLifecycle = new PersistentLifecycle({
344
- start: async () => this._connect(),
345
- stop: async (state) => this._disconnect(state)
346
- }), this._messageListeners = /* @__PURE__ */ new Set(), this._reconnectListeners = /* @__PURE__ */ new Set(), this._currentConnection = void 0, this._ready = new Trigger(), this._isActive = (connection) => connection === this._currentConnection;
567
+ super(), this._identity = _identity, this._config = _config;
347
568
  this._baseWsUrl = getEdgeUrlWithProtocol(_config.socketEndpoint, "ws");
348
569
  this._baseHttpUrl = getEdgeUrlWithProtocol(_config.socketEndpoint, "http");
349
570
  }
@@ -356,7 +577,15 @@ var EdgeClient = class extends Resource2 {
356
577
  };
357
578
  }
358
579
  get status() {
359
- return Boolean(this._currentConnection) && this._ready.state === TriggerState.RESOLVED ? EdgeStatus.CONNECTED : EdgeStatus.NOT_CONNECTED;
580
+ return {
581
+ state: Boolean(this._currentConnection) && this._ready.state === TriggerState.RESOLVED ? EdgeStatus.ConnectionState.CONNECTED : EdgeStatus.ConnectionState.NOT_CONNECTED,
582
+ uptime: this._currentConnection?.uptime ?? 0,
583
+ rtt: this._currentConnection?.rtt ?? 0,
584
+ rateBytesUp: this._currentConnection?.uploadRate ?? 0,
585
+ rateBytesDown: this._currentConnection?.downloadRate ?? 0,
586
+ messagesSent: this._currentConnection?.messagesSent ?? 0,
587
+ messagesReceived: this._currentConnection?.messagesReceived ?? 0
588
+ };
360
589
  }
361
590
  get identityKey() {
362
591
  return this._identity.identityKey;
@@ -370,8 +599,8 @@ var EdgeClient = class extends Resource2 {
370
599
  identity,
371
600
  oldIdentity: this._identity
372
601
  }, {
373
- F: __dxlog_file3,
374
- L: 99,
602
+ F: __dxlog_file4,
603
+ L: 118,
375
604
  S: this,
376
605
  C: (f, a) => f(...a)
377
606
  });
@@ -380,6 +609,30 @@ var EdgeClient = class extends Resource2 {
380
609
  void this._persistentLifecycle.scheduleRestart();
381
610
  }
382
611
  }
612
+ /**
613
+ * Send message.
614
+ * NOTE: The message is guaranteed to be delivered but the service must respond with a message to confirm processing.
615
+ */
616
+ async send(message) {
617
+ if (this._ready.state !== TriggerState.RESOLVED) {
618
+ log2("waiting for websocket", void 0, {
619
+ F: __dxlog_file4,
620
+ L: 131,
621
+ S: this,
622
+ C: (f, a) => f(...a)
623
+ });
624
+ await this._ready.wait({
625
+ timeout: this._config.timeout ?? DEFAULT_TIMEOUT
626
+ });
627
+ }
628
+ if (!this._currentConnection) {
629
+ throw new EdgeConnectionClosedError();
630
+ }
631
+ if (message.source && (message.source.peerKey !== this._identity.peerKey || message.source.identityKey !== this.identityKey)) {
632
+ throw new EdgeIdentityChangedError();
633
+ }
634
+ this._currentConnection.send(message);
635
+ }
383
636
  onMessage(listener) {
384
637
  this._messageListeners.add(listener);
385
638
  return () => this._messageListeners.delete(listener);
@@ -393,8 +646,8 @@ var EdgeClient = class extends Resource2 {
393
646
  listener();
394
647
  } catch (error) {
395
648
  log2.catch(error, void 0, {
396
- F: __dxlog_file3,
397
- L: 121,
649
+ F: __dxlog_file4,
650
+ L: 164,
398
651
  S: this,
399
652
  C: (f, a) => f(...a)
400
653
  });
@@ -411,8 +664,8 @@ var EdgeClient = class extends Resource2 {
411
664
  log2("opening...", {
412
665
  info: this.info
413
666
  }, {
414
- F: __dxlog_file3,
415
- L: 133,
667
+ F: __dxlog_file4,
668
+ L: 177,
416
669
  S: this,
417
670
  C: (f, a) => f(...a)
418
671
  });
@@ -420,12 +673,18 @@ var EdgeClient = class extends Resource2 {
420
673
  log2.warn("Error while opening connection", {
421
674
  err
422
675
  }, {
423
- F: __dxlog_file3,
424
- L: 135,
676
+ F: __dxlog_file4,
677
+ L: 179,
425
678
  S: this,
426
679
  C: (f, a) => f(...a)
427
680
  });
428
681
  });
682
+ scheduleTaskInterval2(this._ctx, async () => {
683
+ if (!this._currentConnection) {
684
+ return;
685
+ }
686
+ this.statusChanged.emit(this.status);
687
+ }, STATUS_REFRESH_INTERVAL);
429
688
  }
430
689
  /**
431
690
  * Close connection and free resources.
@@ -434,8 +693,8 @@ var EdgeClient = class extends Resource2 {
434
693
  log2("closing...", {
435
694
  peerKey: this._identity.peerKey
436
695
  }, {
437
- F: __dxlog_file3,
438
- L: 143,
696
+ F: __dxlog_file4,
697
+ L: 199,
439
698
  S: this,
440
699
  C: (f, a) => f(...a)
441
700
  });
@@ -451,8 +710,8 @@ var EdgeClient = class extends Resource2 {
451
710
  const protocolHeader = this._config.disableAuth ? void 0 : await this._createAuthHeader(path);
452
711
  if (this._identity !== identity) {
453
712
  log2("identity changed during auth header request", void 0, {
454
- F: __dxlog_file3,
455
- L: 157,
713
+ F: __dxlog_file4,
714
+ L: 213,
456
715
  S: this,
457
716
  C: (f, a) => f(...a)
458
717
  });
@@ -464,8 +723,8 @@ var EdgeClient = class extends Resource2 {
464
723
  url: url.toString(),
465
724
  protocolHeader
466
725
  }, {
467
- F: __dxlog_file3,
468
- L: 163,
726
+ F: __dxlog_file4,
727
+ L: 219,
469
728
  S: this,
470
729
  C: (f, a) => f(...a)
471
730
  });
@@ -479,8 +738,8 @@ var EdgeClient = class extends Resource2 {
479
738
  this._notifyReconnected();
480
739
  } else {
481
740
  log2.verbose("connected callback ignored, because connection is not active", void 0, {
482
- F: __dxlog_file3,
483
- L: 173,
741
+ F: __dxlog_file4,
742
+ L: 229,
484
743
  S: this,
485
744
  C: (f, a) => f(...a)
486
745
  });
@@ -492,8 +751,8 @@ var EdgeClient = class extends Resource2 {
492
751
  void this._persistentLifecycle.scheduleRestart();
493
752
  } else {
494
753
  log2.verbose("restart requested by inactive connection", void 0, {
495
- F: __dxlog_file3,
496
- L: 181,
754
+ F: __dxlog_file4,
755
+ L: 237,
497
756
  S: this,
498
757
  C: (f, a) => f(...a)
499
758
  });
@@ -508,8 +767,8 @@ var EdgeClient = class extends Resource2 {
508
767
  from: message.source,
509
768
  type: message.payload?.typeUrl
510
769
  }, {
511
- F: __dxlog_file3,
512
- L: 189,
770
+ F: __dxlog_file4,
771
+ L: 245,
513
772
  S: this,
514
773
  C: (f, a) => f(...a)
515
774
  });
@@ -545,8 +804,8 @@ var EdgeClient = class extends Resource2 {
545
804
  log2.error("ws reconnect listener failed", {
546
805
  err
547
806
  }, {
548
- F: __dxlog_file3,
549
- L: 225,
807
+ F: __dxlog_file4,
808
+ L: 280,
550
809
  S: this,
551
810
  C: (f, a) => f(...a)
552
811
  });
@@ -562,38 +821,14 @@ var EdgeClient = class extends Resource2 {
562
821
  err,
563
822
  payload: protocol.getPayloadType(message)
564
823
  }, {
565
- F: __dxlog_file3,
566
- L: 235,
824
+ F: __dxlog_file4,
825
+ L: 290,
567
826
  S: this,
568
827
  C: (f, a) => f(...a)
569
828
  });
570
829
  }
571
830
  }
572
831
  }
573
- /**
574
- * Send message.
575
- * NOTE: The message is guaranteed to be delivered but the service must respond with a message to confirm processing.
576
- */
577
- async send(message) {
578
- if (this._ready.state !== TriggerState.RESOLVED) {
579
- log2("waiting for websocket to become ready", void 0, {
580
- F: __dxlog_file3,
581
- L: 246,
582
- S: this,
583
- C: (f, a) => f(...a)
584
- });
585
- await this._ready.wait({
586
- timeout: this._config.timeout ?? DEFAULT_TIMEOUT
587
- });
588
- }
589
- if (!this._currentConnection) {
590
- throw new EdgeConnectionClosedError();
591
- }
592
- if (message.source && (message.source.peerKey !== this._identity.peerKey || message.source.identityKey !== this.identityKey)) {
593
- throw new EdgeIdentityChangedError();
594
- }
595
- this._currentConnection.send(message);
596
- }
597
832
  async _createAuthHeader(path) {
598
833
  const httpUrl = new URL(path, this._baseHttpUrl);
599
834
  httpUrl.protocol = getEdgeUrlWithProtocol(this._baseWsUrl.toString(), "http");
@@ -607,14 +842,15 @@ var EdgeClient = class extends Resource2 {
607
842
  status: response.status,
608
843
  statusText: response.statusText
609
844
  }, {
610
- F: __dxlog_file3,
611
- L: 271,
845
+ F: __dxlog_file4,
846
+ L: 302,
612
847
  S: this,
613
848
  C: (f, a) => f(...a)
614
849
  });
615
850
  return void 0;
616
851
  }
617
852
  }
853
+ _isActive = (connection) => connection === this._currentConnection;
618
854
  };
619
855
  _ts_decorate2([
620
856
  logInfo2
@@ -624,144 +860,38 @@ var encodePresentationWsAuthHeader = (encodedPresentation) => {
624
860
  return `base64url.bearer.authorization.dxos.org.${encodedToken}`;
625
861
  };
626
862
 
627
- // src/auth.ts
628
- import { createCredential, signPresentation } from "@dxos/credentials";
629
- import { invariant as invariant3 } from "@dxos/invariant";
630
- import { Keyring } from "@dxos/keyring";
631
- import { PublicKey } from "@dxos/keys";
632
- var __dxlog_file4 = "/__w/dxos/dxos/packages/core/mesh/edge-client/src/auth.ts";
633
- var createDeviceEdgeIdentity = async (signer, key) => {
634
- return {
635
- identityKey: key.toHex(),
636
- peerKey: key.toHex(),
637
- presentCredentials: async ({ challenge }) => {
638
- return signPresentation({
639
- presentation: {
640
- credentials: [
641
- // Verifier requires at least one credential in the presentation to establish the subject.
642
- await createCredential({
643
- assertion: {
644
- "@type": "dxos.halo.credentials.Auth"
645
- },
646
- issuer: key,
647
- subject: key,
648
- signer
649
- })
650
- ]
651
- },
652
- signer,
653
- signerKey: key,
654
- nonce: challenge
655
- });
656
- }
657
- };
658
- };
659
- var createChainEdgeIdentity = async (signer, identityKey, peerKey, chain, credentials) => {
660
- const credentialsToSign = credentials.length > 0 ? credentials : [
661
- await createCredential({
662
- assertion: {
663
- "@type": "dxos.halo.credentials.Auth"
664
- },
665
- issuer: identityKey,
666
- subject: identityKey,
667
- signer,
668
- chain,
669
- signingKey: peerKey
670
- })
671
- ];
672
- return {
673
- identityKey: identityKey.toHex(),
674
- peerKey: peerKey.toHex(),
675
- presentCredentials: async ({ challenge }) => {
676
- invariant3(chain, void 0, {
677
- F: __dxlog_file4,
678
- L: 75,
679
- S: void 0,
680
- A: [
681
- "chain",
682
- ""
683
- ]
684
- });
685
- return signPresentation({
686
- presentation: {
687
- credentials: credentialsToSign
688
- },
689
- signer,
690
- nonce: challenge,
691
- signerKey: peerKey,
692
- chain
693
- });
694
- }
695
- };
696
- };
697
- var createEphemeralEdgeIdentity = async () => {
698
- const keyring = new Keyring();
699
- const key = await keyring.createKey();
700
- return createDeviceEdgeIdentity(keyring, key);
701
- };
702
- var createTestHaloEdgeIdentity = async (signer, identityKey, deviceKey) => {
703
- const deviceAdmission = await createCredential({
704
- assertion: {
705
- "@type": "dxos.halo.credentials.AuthorizedDevice",
706
- deviceKey,
707
- identityKey
708
- },
709
- issuer: identityKey,
710
- subject: deviceKey,
711
- signer
712
- });
713
- return createChainEdgeIdentity(signer, identityKey, deviceKey, {
714
- credential: deviceAdmission
715
- }, [
716
- await createCredential({
717
- assertion: {
718
- "@type": "dxos.halo.credentials.Auth"
719
- },
720
- issuer: identityKey,
721
- subject: identityKey,
722
- signer
723
- })
724
- ]);
725
- };
726
- var createStubEdgeIdentity = () => {
727
- const identityKey = PublicKey.random();
728
- const deviceKey = PublicKey.random();
729
- return {
730
- identityKey: identityKey.toHex(),
731
- peerKey: deviceKey.toHex(),
732
- presentCredentials: async () => {
733
- throw new Error("Stub identity does not support authentication.");
734
- }
735
- };
736
- };
737
-
738
863
  // src/edge-http-client.ts
739
- import { FetchHttpClient, HttpClient } from "@effect/platform";
740
- import { Effect as Effect2, pipe } from "effect";
864
+ import * as FetchHttpClient from "@effect/platform/FetchHttpClient";
865
+ import * as HttpClient from "@effect/platform/HttpClient";
866
+ import * as Effect2 from "effect/Effect";
867
+ import * as Function from "effect/Function";
741
868
  import { sleep } from "@dxos/async";
742
869
  import { Context as Context3 } from "@dxos/context";
870
+ import { invariant as invariant4 } from "@dxos/invariant";
743
871
  import { log as log4 } from "@dxos/log";
744
872
  import { EdgeAuthChallengeError, EdgeCallFailedError } from "@dxos/protocols";
745
873
  import { createUrl } from "@dxos/util";
746
874
 
747
875
  // src/http-client.ts
748
- import { Context as Context2, Duration, Effect, Layer, Schedule } from "effect";
876
+ import * as Context2 from "effect/Context";
877
+ import * as Duration from "effect/Duration";
878
+ import * as Effect from "effect/Effect";
879
+ import * as Layer from "effect/Layer";
880
+ import * as Schedule from "effect/Schedule";
749
881
  import { log as log3 } from "@dxos/log";
750
882
  var __dxlog_file5 = "/__w/dxos/dxos/packages/core/mesh/edge-client/src/http-client.ts";
751
883
  var HttpConfig = class _HttpConfig extends Context2.Tag("HttpConfig")() {
752
- static {
753
- this.default = Layer.succeed(_HttpConfig, {
754
- timeout: Duration.millis(1e3),
755
- retryTimes: 3,
756
- retryBaseDelay: Duration.millis(1e3)
757
- });
758
- }
884
+ static default = Layer.succeed(_HttpConfig, {
885
+ timeout: Duration.millis(1e3),
886
+ retryTimes: 3,
887
+ retryBaseDelay: Duration.millis(1e3)
888
+ });
759
889
  };
760
- var withRetry = (effect, { timeout = Duration.millis(1e3), retryBaseDelay = Duration.millis(1e3), retryTimes = 3 } = {}) => {
890
+ var withRetry = (effect, { timeout: timeout2 = Duration.millis(1e3), retryBaseDelay = Duration.millis(1e3), retryTimes = 3 } = {}) => {
761
891
  return effect.pipe(Effect.flatMap((res) => (
762
892
  // Treat 500 errors as retryable?
763
893
  res.status === 500 ? Effect.fail(new Error(res.status.toString())) : res.json
764
- )), Effect.timeout(timeout), Effect.retry({
894
+ )), Effect.timeout(timeout2), Effect.retry({
765
895
  schedule: Schedule.exponential(retryBaseDelay).pipe(Schedule.jittered),
766
896
  times: retryTimes
767
897
  }));
@@ -770,14 +900,16 @@ var withRetryConfig = (effect) => Effect.gen(function* () {
770
900
  const config = yield* HttpConfig;
771
901
  return yield* withRetry(effect, config);
772
902
  });
773
- var withLogging = (effect) => effect.pipe(Effect.tap((res) => log3.info("response", {
774
- status: res.status
775
- }, {
776
- F: __dxlog_file5,
777
- L: 58,
778
- S: void 0,
779
- C: (f, a) => f(...a)
780
- })));
903
+ var withLogging = (effect) => effect.pipe(Effect.tap((res) => {
904
+ log3.info("response", {
905
+ status: res.status
906
+ }, {
907
+ F: __dxlog_file5,
908
+ L: 66,
909
+ S: void 0,
910
+ C: (f, a) => f(...a)
911
+ });
912
+ }));
781
913
  var encodeAuthHeader = (challenge) => {
782
914
  const encodedChallenge = Buffer.from(challenge).toString("base64");
783
915
  return `VerifiablePresentation pb;base64,${encodedChallenge}`;
@@ -788,14 +920,21 @@ var __dxlog_file6 = "/__w/dxos/dxos/packages/core/mesh/edge-client/src/edge-http
788
920
  var DEFAULT_RETRY_TIMEOUT = 1500;
789
921
  var DEFAULT_RETRY_JITTER = 500;
790
922
  var DEFAULT_MAX_RETRIES_COUNT = 3;
923
+ var WARNING_BODY_SIZE = 10 * 1024 * 1024;
791
924
  var EdgeHttpClient = class {
925
+ _baseUrl;
926
+ _edgeIdentity;
927
+ /**
928
+ * Auth header is cached until receiving the next 401 from EDGE, at which point it gets refreshed.
929
+ */
930
+ _authHeader;
792
931
  constructor(baseUrl) {
793
932
  this._baseUrl = getEdgeUrlWithProtocol(baseUrl, "http");
794
933
  log4("created", {
795
934
  url: this._baseUrl
796
935
  }, {
797
936
  F: __dxlog_file6,
798
- L: 84,
937
+ L: 107,
799
938
  S: this,
800
939
  C: (f, a) => f(...a)
801
940
  });
@@ -927,6 +1066,19 @@ var EdgeHttpClient = class {
927
1066
  // Functions
928
1067
  //
929
1068
  async uploadFunction(pathParts, body, args) {
1069
+ const formData = new FormData();
1070
+ formData.append("name", body.name ?? "");
1071
+ formData.append("version", body.version);
1072
+ formData.append("ownerPublicKey", body.ownerPublicKey);
1073
+ formData.append("entryPoint", body.entryPoint);
1074
+ body.runtime && formData.append("runtime", body.runtime);
1075
+ for (const [filename, content] of Object.entries(body.assets)) {
1076
+ formData.append("assets", new Blob([
1077
+ content
1078
+ ], {
1079
+ type: getFileMimeType(filename)
1080
+ }), filename);
1081
+ }
930
1082
  const path = [
931
1083
  "functions",
932
1084
  ...pathParts.functionId ? [
@@ -935,8 +1087,36 @@ var EdgeHttpClient = class {
935
1087
  ].join("/");
936
1088
  return this._call(new URL(path, this.baseUrl), {
937
1089
  ...args,
938
- body,
939
- method: "PUT"
1090
+ body: formData,
1091
+ method: "PUT",
1092
+ json: false
1093
+ });
1094
+ }
1095
+ async listFunctions(args) {
1096
+ return this._call(new URL("/functions", this.baseUrl), {
1097
+ ...args,
1098
+ method: "GET"
1099
+ });
1100
+ }
1101
+ async invokeFunction(params, input, args) {
1102
+ const url = new URL(`/functions/${params.functionId}`, this.baseUrl);
1103
+ if (params.version) {
1104
+ url.searchParams.set("version", params.version);
1105
+ }
1106
+ if (params.spaceId) {
1107
+ url.searchParams.set("spaceId", params.spaceId.toString());
1108
+ }
1109
+ if (params.cpuTimeLimit) {
1110
+ url.searchParams.set("cpuTimeLimit", params.cpuTimeLimit.toString());
1111
+ }
1112
+ if (params.subrequestsLimit) {
1113
+ url.searchParams.set("subrequestsLimit", params.subrequestsLimit.toString());
1114
+ }
1115
+ return this._call(url, {
1116
+ ...args,
1117
+ body: input,
1118
+ method: "POST",
1119
+ rawResponse: true
940
1120
  });
941
1121
  }
942
1122
  //
@@ -950,71 +1130,136 @@ var EdgeHttpClient = class {
950
1130
  });
951
1131
  }
952
1132
  //
1133
+ // Triggers
1134
+ //
1135
+ async getCronTriggers(spaceId) {
1136
+ return this._call(new URL(`/test/functions/${spaceId}/triggers/crons`, this.baseUrl), {
1137
+ method: "GET"
1138
+ });
1139
+ }
1140
+ //
1141
+ // Import/Export space.
1142
+ //
1143
+ async importBundle(spaceId, body, args) {
1144
+ return this._call(new URL(`/spaces/${spaceId}/import`, this.baseUrl), {
1145
+ ...args,
1146
+ body,
1147
+ method: "PUT"
1148
+ });
1149
+ }
1150
+ async exportBundle(spaceId, body, args) {
1151
+ return this._call(new URL(`/spaces/${spaceId}/export`, this.baseUrl), {
1152
+ ...args,
1153
+ body,
1154
+ method: "POST"
1155
+ });
1156
+ }
1157
+ //
953
1158
  // Internal
954
1159
  //
955
- async _fetch(url, args) {
956
- return pipe(HttpClient.get(url), withLogging, withRetryConfig, Effect2.provide(FetchHttpClient.layer), Effect2.provide(HttpConfig.default), Effect2.withSpan("EdgeHttpClient"), Effect2.runPromise);
1160
+ async _fetch(url, _args) {
1161
+ return Function.pipe(HttpClient.get(url), withLogging, withRetryConfig, Effect2.provide(FetchHttpClient.layer), Effect2.provide(HttpConfig.default), Effect2.withSpan("EdgeHttpClient"), Effect2.runPromise);
957
1162
  }
958
1163
  // TODO(burdon): Refactor with effect (see edge-http-client.test.ts).
959
1164
  async _call(url, args) {
960
1165
  const shouldRetry = createRetryHandler(args);
961
- const requestContext = args.context ?? new Context3(void 0, {
1166
+ const requestContext = args.context ?? Context3.default(void 0, {
962
1167
  F: __dxlog_file6,
963
- L: 289
1168
+ L: 400
964
1169
  });
965
1170
  log4("fetch", {
966
1171
  url,
967
1172
  request: args.body
968
1173
  }, {
969
1174
  F: __dxlog_file6,
970
- L: 290,
1175
+ L: 401,
971
1176
  S: this,
972
1177
  C: (f, a) => f(...a)
973
1178
  });
974
1179
  let handledAuth = false;
1180
+ const tryCount = 1;
975
1181
  while (true) {
976
- let processingError;
977
- let retryAfterHeaderValue = Number.NaN;
1182
+ let processingError = void 0;
978
1183
  try {
1184
+ if (!this._authHeader && args.auth) {
1185
+ const response2 = await fetch(new URL(`/auth`, this.baseUrl));
1186
+ if (response2.status === 401) {
1187
+ this._authHeader = await this._handleUnauthorized(response2);
1188
+ }
1189
+ }
979
1190
  const request = createRequest(args, this._authHeader);
1191
+ log4("call edge", {
1192
+ url,
1193
+ tryCount,
1194
+ authHeader: !!this._authHeader
1195
+ }, {
1196
+ F: __dxlog_file6,
1197
+ L: 416,
1198
+ S: this,
1199
+ C: (f, a) => f(...a)
1200
+ });
980
1201
  const response = await fetch(url, request);
981
- retryAfterHeaderValue = Number(response.headers.get("Retry-After"));
982
1202
  if (response.ok) {
983
- const body = await response.json();
984
- if (body.success) {
985
- return body.data;
1203
+ const body2 = await response.clone().json();
1204
+ if (args.rawResponse) {
1205
+ return body2;
986
1206
  }
987
- log4.warn("unsuccessful edge response", {
988
- url,
989
- body
990
- }, {
1207
+ invariant4(body2, "Expected body to be present", {
991
1208
  F: __dxlog_file6,
992
- L: 306,
1209
+ L: 424,
993
1210
  S: this,
994
- C: (f, a) => f(...a)
1211
+ A: [
1212
+ "body",
1213
+ "'Expected body to be present'"
1214
+ ]
995
1215
  });
996
- if (body.errorData?.type === "auth_challenge" && typeof body.errorData?.challenge === "string") {
997
- processingError = new EdgeAuthChallengeError(body.errorData.challenge, body.errorData);
998
- } else {
999
- processingError = EdgeCallFailedError.fromUnsuccessfulResponse(response, body);
1216
+ if (!("success" in body2)) {
1217
+ return body2;
1218
+ }
1219
+ if (body2.success) {
1220
+ return body2.data;
1000
1221
  }
1001
1222
  } else if (response.status === 401 && !handledAuth) {
1002
1223
  this._authHeader = await this._handleUnauthorized(response);
1003
1224
  handledAuth = true;
1004
1225
  continue;
1226
+ }
1227
+ const body = response.headers.get("Content-Type") === "application/json" ? await response.clone().json() : void 0;
1228
+ invariant4(!body?.success, "Expected body to not be a failure response or undefined.", {
1229
+ F: __dxlog_file6,
1230
+ L: 440,
1231
+ S: this,
1232
+ A: [
1233
+ "!body?.success",
1234
+ "'Expected body to not be a failure response or undefined.'"
1235
+ ]
1236
+ });
1237
+ if (body?.errorData?.type === "auth_challenge" && typeof body?.errorData?.challenge === "string") {
1238
+ processingError = new EdgeAuthChallengeError(body.errorData.challenge, body.errorData);
1239
+ } else if (body?.success === false) {
1240
+ processingError = EdgeCallFailedError.fromUnsuccessfulResponse(response, body);
1005
1241
  } else {
1006
- processingError = EdgeCallFailedError.fromHttpFailure(response);
1242
+ invariant4(!response.ok, "Expected response to not be ok.", {
1243
+ F: __dxlog_file6,
1244
+ L: 447,
1245
+ S: this,
1246
+ A: [
1247
+ "!response.ok",
1248
+ "'Expected response to not be ok.'"
1249
+ ]
1250
+ });
1251
+ processingError = await EdgeCallFailedError.fromHttpFailure(response);
1007
1252
  }
1008
1253
  } catch (error) {
1009
1254
  processingError = EdgeCallFailedError.fromProcessingFailureCause(error);
1010
1255
  }
1011
- if (processingError.isRetryable && await shouldRetry(requestContext, retryAfterHeaderValue)) {
1012
- log4("retrying edge request", {
1256
+ if (processingError?.isRetryable && await shouldRetry(requestContext, processingError.retryAfterMs)) {
1257
+ log4.verbose("retrying edge request", {
1013
1258
  url,
1014
1259
  processingError
1015
1260
  }, {
1016
1261
  F: __dxlog_file6,
1017
- L: 324,
1262
+ L: 455,
1018
1263
  S: this,
1019
1264
  C: (f, a) => f(...a)
1020
1265
  });
@@ -1027,33 +1272,52 @@ var EdgeHttpClient = class {
1027
1272
  if (!this._edgeIdentity) {
1028
1273
  log4.warn("unauthorized response received before identity was set", void 0, {
1029
1274
  F: __dxlog_file6,
1030
- L: 333,
1275
+ L: 464,
1031
1276
  S: this,
1032
1277
  C: (f, a) => f(...a)
1033
1278
  });
1034
- throw EdgeCallFailedError.fromHttpFailure(response);
1279
+ throw await EdgeCallFailedError.fromHttpFailure(response);
1035
1280
  }
1036
1281
  const challenge = await handleAuthChallenge(response, this._edgeIdentity);
1037
1282
  return encodeAuthHeader(challenge);
1038
1283
  }
1039
1284
  };
1040
- var createRequest = ({ method, body }, authHeader) => {
1285
+ var createRequest = ({ method, body, json = true }, authHeader) => {
1286
+ let requestBody;
1287
+ const headers = {};
1288
+ if (json) {
1289
+ requestBody = body && JSON.stringify(body);
1290
+ headers["Content-Type"] = "application/json";
1291
+ } else {
1292
+ requestBody = body;
1293
+ }
1294
+ if (typeof requestBody === "string" && requestBody.length > WARNING_BODY_SIZE) {
1295
+ log4.warn("Request with large body", {
1296
+ bodySize: requestBody.length
1297
+ }, {
1298
+ F: __dxlog_file6,
1299
+ L: 488,
1300
+ S: void 0,
1301
+ C: (f, a) => f(...a)
1302
+ });
1303
+ }
1304
+ if (authHeader) {
1305
+ headers["Authorization"] = authHeader;
1306
+ }
1041
1307
  return {
1042
1308
  method,
1043
- body: body && JSON.stringify(body),
1044
- headers: authHeader ? {
1045
- Authorization: authHeader
1046
- } : void 0
1309
+ body: requestBody,
1310
+ headers
1047
1311
  };
1048
1312
  };
1049
- var createRetryHandler = ({ retry }) => {
1050
- if (!retry || retry.count < 1) {
1313
+ var createRetryHandler = ({ retry: retry2 }) => {
1314
+ if (!retry2 || retry2.count < 1) {
1051
1315
  return async () => false;
1052
1316
  }
1053
1317
  let retries = 0;
1054
- const maxRetries = retry.count ?? DEFAULT_MAX_RETRIES_COUNT;
1055
- const baseTimeout = retry.timeout ?? DEFAULT_RETRY_TIMEOUT;
1056
- const jitter = retry.jitter ?? DEFAULT_RETRY_JITTER;
1318
+ const maxRetries = retry2.count ?? DEFAULT_MAX_RETRIES_COUNT;
1319
+ const baseTimeout = retry2.timeout ?? DEFAULT_RETRY_TIMEOUT;
1320
+ const jitter = retry2.jitter ?? DEFAULT_RETRY_JITTER;
1057
1321
  return async (ctx, retryAfter) => {
1058
1322
  if (++retries > maxRetries || ctx.disposed) {
1059
1323
  return false;
@@ -1061,12 +1325,16 @@ var createRetryHandler = ({ retry }) => {
1061
1325
  if (retryAfter) {
1062
1326
  await sleep(retryAfter);
1063
1327
  } else {
1064
- const timeout = baseTimeout + Math.random() * jitter;
1065
- await sleep(timeout);
1328
+ const timeout2 = baseTimeout + Math.random() * jitter;
1329
+ await sleep(timeout2);
1066
1330
  }
1067
1331
  return true;
1068
1332
  };
1069
1333
  };
1334
+ var getFileMimeType = (filename) => [
1335
+ ".js",
1336
+ ".mjs"
1337
+ ].some((codeExtension) => filename.endsWith(codeExtension)) ? "application/javascript+module" : filename.endsWith(".wasm") ? "application/wasm" : "application/octet-stream";
1070
1338
  export {
1071
1339
  CLOUDFLARE_MESSAGE_MAX_BYTES,
1072
1340
  CLOUDFLARE_RPC_MAX_BYTES,
@@ -1074,6 +1342,7 @@ export {
1074
1342
  EdgeConnectionClosedError,
1075
1343
  EdgeHttpClient,
1076
1344
  EdgeIdentityChangedError,
1345
+ HttpConfig,
1077
1346
  Protocol,
1078
1347
  WebSocketMuxer,
1079
1348
  createChainEdgeIdentity,
@@ -1081,9 +1350,13 @@ export {
1081
1350
  createEphemeralEdgeIdentity,
1082
1351
  createStubEdgeIdentity,
1083
1352
  createTestHaloEdgeIdentity,
1353
+ encodeAuthHeader,
1084
1354
  getTypename,
1085
1355
  handleAuthChallenge,
1086
1356
  protocol,
1087
- toUint8Array
1357
+ toUint8Array,
1358
+ withLogging,
1359
+ withRetry,
1360
+ withRetryConfig
1088
1361
  };
1089
1362
  //# sourceMappingURL=index.mjs.map