@dxos/edge-client 0.8.4-main.fd6878d → 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 (38) hide show
  1. package/dist/lib/browser/{chunk-SUXH7FH6.mjs → chunk-VESGVCLQ.mjs} +4 -7
  2. package/dist/lib/browser/{chunk-SUXH7FH6.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 +525 -287
  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-R6K4IIBW.mjs → chunk-JTBFRYNM.mjs} +4 -7
  10. package/dist/lib/node-esm/{chunk-R6K4IIBW.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 +525 -287
  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 +14 -14
  18. package/dist/types/src/edge-client.d.ts.map +1 -1
  19. package/dist/types/src/edge-http-client.d.ts +30 -4
  20. package/dist/types/src/edge-http-client.d.ts.map +1 -1
  21. package/dist/types/src/edge-ws-connection.d.ts +19 -0
  22. package/dist/types/src/edge-ws-connection.d.ts.map +1 -1
  23. package/dist/types/src/http-client.d.ts +10 -7
  24. package/dist/types/src/http-client.d.ts.map +1 -1
  25. package/dist/types/src/index.d.ts +4 -3
  26. package/dist/types/src/index.d.ts.map +1 -1
  27. package/dist/types/src/testing/test-utils.d.ts +1 -1
  28. package/dist/types/tsconfig.tsbuildinfo +1 -1
  29. package/package.json +15 -15
  30. package/src/edge-client.test.ts +4 -4
  31. package/src/edge-client.ts +72 -41
  32. package/src/edge-http-client.test.ts +1 -1
  33. package/src/edge-http-client.ts +188 -33
  34. package/src/edge-ws-connection.ts +118 -5
  35. package/src/http-client.test.ts +8 -5
  36. package/src/http-client.ts +18 -8
  37. package/src/index.ts +4 -3
  38. package/src/testing/test-utils.ts +3 -3
@@ -6,24 +6,135 @@ import {
6
6
  getTypename,
7
7
  protocol,
8
8
  toUint8Array
9
- } from "./chunk-SUXH7FH6.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 { Event, PersistentLifecycle, Trigger, TriggerState, scheduleMicroTask } 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,7 +183,7 @@ 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 {
@@ -82,9 +193,21 @@ var EdgeWsConnection = class extends Resource {
82
193
  _inactivityTimeoutCtx;
83
194
  _ws;
84
195
  _wsMuxer;
85
- _lastReceivedMessageTimestamp;
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;
86
209
  constructor(_identity, _connectionInfo, _callbacks) {
87
- super(), this._identity = _identity, this._connectionInfo = _connectionInfo, this._callbacks = _callbacks, this._lastReceivedMessageTimestamp = Date.now();
210
+ super(), this._identity = _identity, this._connectionInfo = _connectionInfo, this._callbacks = _callbacks;
88
211
  }
89
212
  get info() {
90
213
  return {
@@ -93,19 +216,37 @@ var EdgeWsConnection = class extends Resource {
93
216
  device: this._identity.peerKey
94
217
  };
95
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
+ }
96
237
  send(message) {
97
- invariant2(this._ws, void 0, {
98
- F: __dxlog_file2,
99
- L: 53,
238
+ invariant3(this._ws, void 0, {
239
+ F: __dxlog_file3,
240
+ L: 93,
100
241
  S: this,
101
242
  A: [
102
243
  "this._ws",
103
244
  ""
104
245
  ]
105
246
  });
106
- invariant2(this._wsMuxer, void 0, {
107
- F: __dxlog_file2,
108
- L: 54,
247
+ invariant3(this._wsMuxer, void 0, {
248
+ F: __dxlog_file3,
249
+ L: 94,
109
250
  S: this,
110
251
  A: [
111
252
  "this._wsMuxer",
@@ -116,11 +257,12 @@ var EdgeWsConnection = class extends Resource {
116
257
  peerKey: this._identity.peerKey,
117
258
  payload: protocol.getPayloadType(message)
118
259
  }, {
119
- F: __dxlog_file2,
120
- L: 55,
260
+ F: __dxlog_file3,
261
+ L: 95,
121
262
  S: this,
122
263
  C: (f, a) => f(...a)
123
264
  });
265
+ this._messagesSent++;
124
266
  if (this._ws?.protocol.includes(EdgeWebsocketProtocol.V0)) {
125
267
  const binary = buf.toBinary(MessageSchema, message);
126
268
  if (binary.length > CLOUDFLARE_MESSAGE_MAX_BYTES) {
@@ -129,18 +271,21 @@ var EdgeWsConnection = class extends Resource {
129
271
  serviceId: message.serviceId,
130
272
  payload: protocol.getPayloadType(message)
131
273
  }, {
132
- F: __dxlog_file2,
133
- L: 59,
274
+ F: __dxlog_file3,
275
+ L: 100,
134
276
  S: this,
135
277
  C: (f, a) => f(...a)
136
278
  });
137
279
  return;
138
280
  }
281
+ this._recordBytes(binary.byteLength, 0);
139
282
  this._ws.send(binary);
140
283
  } else {
284
+ const binary = buf.toBinary(MessageSchema, message);
285
+ this._recordBytes(binary.byteLength, 0);
141
286
  this._wsMuxer.send(message).catch((e) => log.catch(e, void 0, {
142
- F: __dxlog_file2,
143
- L: 68,
287
+ F: __dxlog_file3,
288
+ L: 113,
144
289
  S: this,
145
290
  C: (f, a) => f(...a)
146
291
  }));
@@ -161,19 +306,21 @@ var EdgeWsConnection = class extends Resource {
161
306
  this._ws.onopen = () => {
162
307
  if (this.isOpen) {
163
308
  log("connected", void 0, {
164
- F: __dxlog_file2,
165
- L: 85,
309
+ F: __dxlog_file3,
310
+ L: 130,
166
311
  S: this,
167
312
  C: (f, a) => f(...a)
168
313
  });
314
+ this._openTimestamp = Date.now();
169
315
  this._callbacks.onConnected();
170
316
  this._scheduleHeartbeats();
317
+ this._scheduleRateCalculation();
171
318
  } else {
172
319
  log.verbose("connected after becoming inactive", {
173
320
  currentIdentity: this._identity
174
321
  }, {
175
- F: __dxlog_file2,
176
- L: 89,
322
+ F: __dxlog_file3,
323
+ L: 136,
177
324
  S: this,
178
325
  C: (f, a) => f(...a)
179
326
  });
@@ -181,12 +328,12 @@ var EdgeWsConnection = class extends Resource {
181
328
  };
182
329
  this._ws.onclose = (event) => {
183
330
  if (this.isOpen) {
184
- log.warn("disconnected while being open", {
331
+ log.warn("server disconnected", {
185
332
  code: event.code,
186
333
  reason: event.reason
187
334
  }, {
188
- F: __dxlog_file2,
189
- L: 94,
335
+ F: __dxlog_file3,
336
+ L: 141,
190
337
  S: this,
191
338
  C: (f, a) => f(...a)
192
339
  });
@@ -200,8 +347,8 @@ var EdgeWsConnection = class extends Resource {
200
347
  error: event.error,
201
348
  info: event.message
202
349
  }, {
203
- F: __dxlog_file2,
204
- L: 101,
350
+ F: __dxlog_file3,
351
+ L: 148,
205
352
  S: this,
206
353
  C: (f, a) => f(...a)
207
354
  });
@@ -210,8 +357,8 @@ var EdgeWsConnection = class extends Resource {
210
357
  log.verbose("error ignored on closed connection", {
211
358
  error: event.error
212
359
  }, {
213
- F: __dxlog_file2,
214
- L: 104,
360
+ F: __dxlog_file3,
361
+ L: 151,
215
362
  S: this,
216
363
  C: (f, a) => f(...a)
217
364
  });
@@ -222,8 +369,8 @@ var EdgeWsConnection = class extends Resource {
222
369
  log.verbose("message ignored on closed connection", {
223
370
  event: event.type
224
371
  }, {
225
- F: __dxlog_file2,
226
- L: 112,
372
+ F: __dxlog_file3,
373
+ L: 159,
227
374
  S: this,
228
375
  C: (f, a) => f(...a)
229
376
  });
@@ -231,21 +378,27 @@ var EdgeWsConnection = class extends Resource {
231
378
  }
232
379
  this._lastReceivedMessageTimestamp = Date.now();
233
380
  if (event.data === "__pong__") {
381
+ if (this._pingTimestamp) {
382
+ this._rtt = Date.now() - this._pingTimestamp;
383
+ this._pingTimestamp = void 0;
384
+ }
234
385
  this._rescheduleHeartbeatTimeout();
235
386
  return;
236
387
  }
237
388
  const bytes = await toUint8Array(event.data);
389
+ this._recordBytes(0, bytes.byteLength);
238
390
  if (!this.isOpen) {
239
391
  return;
240
392
  }
393
+ this._messagesReceived++;
241
394
  const message = this._ws?.protocol?.includes(EdgeWebsocketProtocol.V0) ? buf.fromBinary(MessageSchema, bytes) : muxer.receiveData(bytes);
242
395
  if (message) {
243
396
  log("received", {
244
397
  from: message.source,
245
398
  payload: protocol.getPayloadType(message)
246
399
  }, {
247
- F: __dxlog_file2,
248
- L: 130,
400
+ F: __dxlog_file3,
401
+ L: 185,
249
402
  S: this,
250
403
  C: (f, a) => f(...a)
251
404
  });
@@ -265,20 +418,20 @@ var EdgeWsConnection = class extends Resource {
265
418
  if (err instanceof Error && err.message.includes("WebSocket is closed before the connection is established.")) {
266
419
  return;
267
420
  }
268
- log.warn("Error closing websocket", {
421
+ log.warn("error closing websocket", {
269
422
  err
270
423
  }, {
271
- F: __dxlog_file2,
272
- L: 148,
424
+ F: __dxlog_file3,
425
+ L: 203,
273
426
  S: this,
274
427
  C: (f, a) => f(...a)
275
428
  });
276
429
  }
277
430
  }
278
431
  _scheduleHeartbeats() {
279
- invariant2(this._ws, void 0, {
280
- F: __dxlog_file2,
281
- L: 153,
432
+ invariant3(this._ws, void 0, {
433
+ F: __dxlog_file3,
434
+ L: 208,
282
435
  S: this,
283
436
  A: [
284
437
  "this._ws",
@@ -286,8 +439,10 @@ var EdgeWsConnection = class extends Resource {
286
439
  ]
287
440
  });
288
441
  scheduleTaskInterval(this._ctx, async () => {
442
+ this._pingTimestamp = Date.now();
289
443
  this._ws?.send("__ping__");
290
444
  }, SIGNAL_KEEPALIVE_INTERVAL);
445
+ this._pingTimestamp = Date.now();
291
446
  this._ws.send("__ping__");
292
447
  this._rescheduleHeartbeatTimeout();
293
448
  }
@@ -297,8 +452,8 @@ var EdgeWsConnection = class extends Resource {
297
452
  }
298
453
  void this._inactivityTimeoutCtx?.dispose();
299
454
  this._inactivityTimeoutCtx = new Context(void 0, {
300
- F: __dxlog_file2,
301
- L: 172
455
+ F: __dxlog_file3,
456
+ L: 229
302
457
  });
303
458
  scheduleTask(this._inactivityTimeoutCtx, () => {
304
459
  if (this.isOpen) {
@@ -306,8 +461,8 @@ var EdgeWsConnection = class extends Resource {
306
461
  log.warn("restart due to inactivity timeout", {
307
462
  lastReceivedMessageTimestamp: this._lastReceivedMessageTimestamp
308
463
  }, {
309
- F: __dxlog_file2,
310
- L: 178,
464
+ F: __dxlog_file3,
465
+ L: 235,
311
466
  S: this,
312
467
  C: (f, a) => f(...a)
313
468
  });
@@ -318,6 +473,47 @@ var EdgeWsConnection = class extends Resource {
318
473
  }
319
474
  }, SIGNAL_KEEPALIVE_TIMEOUT);
320
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
+ }
321
517
  };
322
518
  _ts_decorate([
323
519
  logInfo
@@ -350,24 +546,25 @@ function _ts_decorate2(decorators, target, key, desc) {
350
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;
351
547
  return c > 3 && r && Object.defineProperty(target, key, r), r;
352
548
  }
353
- 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";
354
550
  var DEFAULT_TIMEOUT = 1e4;
551
+ var STATUS_REFRESH_INTERVAL = 1e3;
355
552
  var EdgeClient = class extends Resource2 {
356
553
  _identity;
357
554
  _config;
358
- statusChanged;
359
- _persistentLifecycle;
360
- _messageListeners;
361
- _reconnectListeners;
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();
362
562
  _baseWsUrl;
363
563
  _baseHttpUrl;
364
- _currentConnection;
365
- _ready;
564
+ _currentConnection = void 0;
565
+ _ready = new Trigger();
366
566
  constructor(_identity, _config) {
367
- super(), this._identity = _identity, this._config = _config, this.statusChanged = new Event(), this._persistentLifecycle = new PersistentLifecycle({
368
- start: async () => this._connect(),
369
- stop: async (state) => this._disconnect(state)
370
- }), 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;
371
568
  this._baseWsUrl = getEdgeUrlWithProtocol(_config.socketEndpoint, "ws");
372
569
  this._baseHttpUrl = getEdgeUrlWithProtocol(_config.socketEndpoint, "http");
373
570
  }
@@ -380,7 +577,15 @@ var EdgeClient = class extends Resource2 {
380
577
  };
381
578
  }
382
579
  get status() {
383
- 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
+ };
384
589
  }
385
590
  get identityKey() {
386
591
  return this._identity.identityKey;
@@ -394,8 +599,8 @@ var EdgeClient = class extends Resource2 {
394
599
  identity,
395
600
  oldIdentity: this._identity
396
601
  }, {
397
- F: __dxlog_file3,
398
- L: 99,
602
+ F: __dxlog_file4,
603
+ L: 118,
399
604
  S: this,
400
605
  C: (f, a) => f(...a)
401
606
  });
@@ -404,6 +609,30 @@ var EdgeClient = class extends Resource2 {
404
609
  void this._persistentLifecycle.scheduleRestart();
405
610
  }
406
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
+ }
407
636
  onMessage(listener) {
408
637
  this._messageListeners.add(listener);
409
638
  return () => this._messageListeners.delete(listener);
@@ -417,8 +646,8 @@ var EdgeClient = class extends Resource2 {
417
646
  listener();
418
647
  } catch (error) {
419
648
  log2.catch(error, void 0, {
420
- F: __dxlog_file3,
421
- L: 121,
649
+ F: __dxlog_file4,
650
+ L: 164,
422
651
  S: this,
423
652
  C: (f, a) => f(...a)
424
653
  });
@@ -435,8 +664,8 @@ var EdgeClient = class extends Resource2 {
435
664
  log2("opening...", {
436
665
  info: this.info
437
666
  }, {
438
- F: __dxlog_file3,
439
- L: 133,
667
+ F: __dxlog_file4,
668
+ L: 177,
440
669
  S: this,
441
670
  C: (f, a) => f(...a)
442
671
  });
@@ -444,12 +673,18 @@ var EdgeClient = class extends Resource2 {
444
673
  log2.warn("Error while opening connection", {
445
674
  err
446
675
  }, {
447
- F: __dxlog_file3,
448
- L: 135,
676
+ F: __dxlog_file4,
677
+ L: 179,
449
678
  S: this,
450
679
  C: (f, a) => f(...a)
451
680
  });
452
681
  });
682
+ scheduleTaskInterval2(this._ctx, async () => {
683
+ if (!this._currentConnection) {
684
+ return;
685
+ }
686
+ this.statusChanged.emit(this.status);
687
+ }, STATUS_REFRESH_INTERVAL);
453
688
  }
454
689
  /**
455
690
  * Close connection and free resources.
@@ -458,8 +693,8 @@ var EdgeClient = class extends Resource2 {
458
693
  log2("closing...", {
459
694
  peerKey: this._identity.peerKey
460
695
  }, {
461
- F: __dxlog_file3,
462
- L: 143,
696
+ F: __dxlog_file4,
697
+ L: 199,
463
698
  S: this,
464
699
  C: (f, a) => f(...a)
465
700
  });
@@ -475,8 +710,8 @@ var EdgeClient = class extends Resource2 {
475
710
  const protocolHeader = this._config.disableAuth ? void 0 : await this._createAuthHeader(path);
476
711
  if (this._identity !== identity) {
477
712
  log2("identity changed during auth header request", void 0, {
478
- F: __dxlog_file3,
479
- L: 157,
713
+ F: __dxlog_file4,
714
+ L: 213,
480
715
  S: this,
481
716
  C: (f, a) => f(...a)
482
717
  });
@@ -488,8 +723,8 @@ var EdgeClient = class extends Resource2 {
488
723
  url: url.toString(),
489
724
  protocolHeader
490
725
  }, {
491
- F: __dxlog_file3,
492
- L: 163,
726
+ F: __dxlog_file4,
727
+ L: 219,
493
728
  S: this,
494
729
  C: (f, a) => f(...a)
495
730
  });
@@ -503,8 +738,8 @@ var EdgeClient = class extends Resource2 {
503
738
  this._notifyReconnected();
504
739
  } else {
505
740
  log2.verbose("connected callback ignored, because connection is not active", void 0, {
506
- F: __dxlog_file3,
507
- L: 173,
741
+ F: __dxlog_file4,
742
+ L: 229,
508
743
  S: this,
509
744
  C: (f, a) => f(...a)
510
745
  });
@@ -516,8 +751,8 @@ var EdgeClient = class extends Resource2 {
516
751
  void this._persistentLifecycle.scheduleRestart();
517
752
  } else {
518
753
  log2.verbose("restart requested by inactive connection", void 0, {
519
- F: __dxlog_file3,
520
- L: 181,
754
+ F: __dxlog_file4,
755
+ L: 237,
521
756
  S: this,
522
757
  C: (f, a) => f(...a)
523
758
  });
@@ -532,8 +767,8 @@ var EdgeClient = class extends Resource2 {
532
767
  from: message.source,
533
768
  type: message.payload?.typeUrl
534
769
  }, {
535
- F: __dxlog_file3,
536
- L: 189,
770
+ F: __dxlog_file4,
771
+ L: 245,
537
772
  S: this,
538
773
  C: (f, a) => f(...a)
539
774
  });
@@ -569,8 +804,8 @@ var EdgeClient = class extends Resource2 {
569
804
  log2.error("ws reconnect listener failed", {
570
805
  err
571
806
  }, {
572
- F: __dxlog_file3,
573
- L: 225,
807
+ F: __dxlog_file4,
808
+ L: 280,
574
809
  S: this,
575
810
  C: (f, a) => f(...a)
576
811
  });
@@ -586,38 +821,14 @@ var EdgeClient = class extends Resource2 {
586
821
  err,
587
822
  payload: protocol.getPayloadType(message)
588
823
  }, {
589
- F: __dxlog_file3,
590
- L: 235,
824
+ F: __dxlog_file4,
825
+ L: 290,
591
826
  S: this,
592
827
  C: (f, a) => f(...a)
593
828
  });
594
829
  }
595
830
  }
596
831
  }
597
- /**
598
- * Send message.
599
- * NOTE: The message is guaranteed to be delivered but the service must respond with a message to confirm processing.
600
- */
601
- async send(message) {
602
- if (this._ready.state !== TriggerState.RESOLVED) {
603
- log2("waiting for websocket to become ready", void 0, {
604
- F: __dxlog_file3,
605
- L: 246,
606
- S: this,
607
- C: (f, a) => f(...a)
608
- });
609
- await this._ready.wait({
610
- timeout: this._config.timeout ?? DEFAULT_TIMEOUT
611
- });
612
- }
613
- if (!this._currentConnection) {
614
- throw new EdgeConnectionClosedError();
615
- }
616
- if (message.source && (message.source.peerKey !== this._identity.peerKey || message.source.identityKey !== this.identityKey)) {
617
- throw new EdgeIdentityChangedError();
618
- }
619
- this._currentConnection.send(message);
620
- }
621
832
  async _createAuthHeader(path) {
622
833
  const httpUrl = new URL(path, this._baseHttpUrl);
623
834
  httpUrl.protocol = getEdgeUrlWithProtocol(this._baseWsUrl.toString(), "http");
@@ -631,15 +842,15 @@ var EdgeClient = class extends Resource2 {
631
842
  status: response.status,
632
843
  statusText: response.statusText
633
844
  }, {
634
- F: __dxlog_file3,
635
- L: 271,
845
+ F: __dxlog_file4,
846
+ L: 302,
636
847
  S: this,
637
848
  C: (f, a) => f(...a)
638
849
  });
639
850
  return void 0;
640
851
  }
641
852
  }
642
- _isActive;
853
+ _isActive = (connection) => connection === this._currentConnection;
643
854
  };
644
855
  _ts_decorate2([
645
856
  logInfo2
@@ -649,128 +860,24 @@ var encodePresentationWsAuthHeader = (encodedPresentation) => {
649
860
  return `base64url.bearer.authorization.dxos.org.${encodedToken}`;
650
861
  };
651
862
 
652
- // src/auth.ts
653
- import { createCredential, signPresentation } from "@dxos/credentials";
654
- import { invariant as invariant3 } from "@dxos/invariant";
655
- import { Keyring } from "@dxos/keyring";
656
- import { PublicKey } from "@dxos/keys";
657
- var __dxlog_file4 = "/__w/dxos/dxos/packages/core/mesh/edge-client/src/auth.ts";
658
- var createDeviceEdgeIdentity = async (signer, key) => {
659
- return {
660
- identityKey: key.toHex(),
661
- peerKey: key.toHex(),
662
- presentCredentials: async ({ challenge }) => {
663
- return signPresentation({
664
- presentation: {
665
- credentials: [
666
- // Verifier requires at least one credential in the presentation to establish the subject.
667
- await createCredential({
668
- assertion: {
669
- "@type": "dxos.halo.credentials.Auth"
670
- },
671
- issuer: key,
672
- subject: key,
673
- signer
674
- })
675
- ]
676
- },
677
- signer,
678
- signerKey: key,
679
- nonce: challenge
680
- });
681
- }
682
- };
683
- };
684
- var createChainEdgeIdentity = async (signer, identityKey, peerKey, chain, credentials) => {
685
- const credentialsToSign = credentials.length > 0 ? credentials : [
686
- await createCredential({
687
- assertion: {
688
- "@type": "dxos.halo.credentials.Auth"
689
- },
690
- issuer: identityKey,
691
- subject: identityKey,
692
- signer,
693
- chain,
694
- signingKey: peerKey
695
- })
696
- ];
697
- return {
698
- identityKey: identityKey.toHex(),
699
- peerKey: peerKey.toHex(),
700
- presentCredentials: async ({ challenge }) => {
701
- invariant3(chain, void 0, {
702
- F: __dxlog_file4,
703
- L: 75,
704
- S: void 0,
705
- A: [
706
- "chain",
707
- ""
708
- ]
709
- });
710
- return signPresentation({
711
- presentation: {
712
- credentials: credentialsToSign
713
- },
714
- signer,
715
- nonce: challenge,
716
- signerKey: peerKey,
717
- chain
718
- });
719
- }
720
- };
721
- };
722
- var createEphemeralEdgeIdentity = async () => {
723
- const keyring = new Keyring();
724
- const key = await keyring.createKey();
725
- return createDeviceEdgeIdentity(keyring, key);
726
- };
727
- var createTestHaloEdgeIdentity = async (signer, identityKey, deviceKey) => {
728
- const deviceAdmission = await createCredential({
729
- assertion: {
730
- "@type": "dxos.halo.credentials.AuthorizedDevice",
731
- deviceKey,
732
- identityKey
733
- },
734
- issuer: identityKey,
735
- subject: deviceKey,
736
- signer
737
- });
738
- return createChainEdgeIdentity(signer, identityKey, deviceKey, {
739
- credential: deviceAdmission
740
- }, [
741
- await createCredential({
742
- assertion: {
743
- "@type": "dxos.halo.credentials.Auth"
744
- },
745
- issuer: identityKey,
746
- subject: identityKey,
747
- signer
748
- })
749
- ]);
750
- };
751
- var createStubEdgeIdentity = () => {
752
- const identityKey = PublicKey.random();
753
- const deviceKey = PublicKey.random();
754
- return {
755
- identityKey: identityKey.toHex(),
756
- peerKey: deviceKey.toHex(),
757
- presentCredentials: async () => {
758
- throw new Error("Stub identity does not support authentication.");
759
- }
760
- };
761
- };
762
-
763
863
  // src/edge-http-client.ts
764
- import { FetchHttpClient, HttpClient } from "@effect/platform";
765
- 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";
766
868
  import { sleep } from "@dxos/async";
767
869
  import { Context as Context3 } from "@dxos/context";
870
+ import { invariant as invariant4 } from "@dxos/invariant";
768
871
  import { log as log4 } from "@dxos/log";
769
872
  import { EdgeAuthChallengeError, EdgeCallFailedError } from "@dxos/protocols";
770
873
  import { createUrl } from "@dxos/util";
771
874
 
772
875
  // src/http-client.ts
773
- 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";
774
881
  import { log as log3 } from "@dxos/log";
775
882
  var __dxlog_file5 = "/__w/dxos/dxos/packages/core/mesh/edge-client/src/http-client.ts";
776
883
  var HttpConfig = class _HttpConfig extends Context2.Tag("HttpConfig")() {
@@ -780,11 +887,11 @@ var HttpConfig = class _HttpConfig extends Context2.Tag("HttpConfig")() {
780
887
  retryBaseDelay: Duration.millis(1e3)
781
888
  });
782
889
  };
783
- 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 } = {}) => {
784
891
  return effect.pipe(Effect.flatMap((res) => (
785
892
  // Treat 500 errors as retryable?
786
893
  res.status === 500 ? Effect.fail(new Error(res.status.toString())) : res.json
787
- )), Effect.timeout(timeout), Effect.retry({
894
+ )), Effect.timeout(timeout2), Effect.retry({
788
895
  schedule: Schedule.exponential(retryBaseDelay).pipe(Schedule.jittered),
789
896
  times: retryTimes
790
897
  }));
@@ -793,14 +900,16 @@ var withRetryConfig = (effect) => Effect.gen(function* () {
793
900
  const config = yield* HttpConfig;
794
901
  return yield* withRetry(effect, config);
795
902
  });
796
- var withLogging = (effect) => effect.pipe(Effect.tap((res) => log3.info("response", {
797
- status: res.status
798
- }, {
799
- F: __dxlog_file5,
800
- L: 58,
801
- S: void 0,
802
- C: (f, a) => f(...a)
803
- })));
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
+ }));
804
913
  var encodeAuthHeader = (challenge) => {
805
914
  const encodedChallenge = Buffer.from(challenge).toString("base64");
806
915
  return `VerifiablePresentation pb;base64,${encodedChallenge}`;
@@ -811,6 +920,7 @@ var __dxlog_file6 = "/__w/dxos/dxos/packages/core/mesh/edge-client/src/edge-http
811
920
  var DEFAULT_RETRY_TIMEOUT = 1500;
812
921
  var DEFAULT_RETRY_JITTER = 500;
813
922
  var DEFAULT_MAX_RETRIES_COUNT = 3;
923
+ var WARNING_BODY_SIZE = 10 * 1024 * 1024;
814
924
  var EdgeHttpClient = class {
815
925
  _baseUrl;
816
926
  _edgeIdentity;
@@ -824,7 +934,7 @@ var EdgeHttpClient = class {
824
934
  url: this._baseUrl
825
935
  }, {
826
936
  F: __dxlog_file6,
827
- L: 84,
937
+ L: 107,
828
938
  S: this,
829
939
  C: (f, a) => f(...a)
830
940
  });
@@ -902,12 +1012,6 @@ var EdgeHttpClient = class {
902
1012
  //
903
1013
  // OAuth and credentials
904
1014
  //
905
- async listFunctions(args) {
906
- return this._call(new URL("/functions", this.baseUrl), {
907
- ...args,
908
- method: "GET"
909
- });
910
- }
911
1015
  async initiateOAuthFlow(body, args) {
912
1016
  return this._call(new URL("/oauth/initiate", this.baseUrl), {
913
1017
  ...args,
@@ -962,6 +1066,19 @@ var EdgeHttpClient = class {
962
1066
  // Functions
963
1067
  //
964
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
+ }
965
1082
  const path = [
966
1083
  "functions",
967
1084
  ...pathParts.functionId ? [
@@ -970,8 +1087,36 @@ var EdgeHttpClient = class {
970
1087
  ].join("/");
971
1088
  return this._call(new URL(path, this.baseUrl), {
972
1089
  ...args,
973
- body,
974
- 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
975
1120
  });
976
1121
  }
977
1122
  //
@@ -985,71 +1130,136 @@ var EdgeHttpClient = class {
985
1130
  });
986
1131
  }
987
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
+ //
988
1158
  // Internal
989
1159
  //
990
- async _fetch(url, args) {
991
- 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);
992
1162
  }
993
1163
  // TODO(burdon): Refactor with effect (see edge-http-client.test.ts).
994
1164
  async _call(url, args) {
995
1165
  const shouldRetry = createRetryHandler(args);
996
- const requestContext = args.context ?? new Context3(void 0, {
1166
+ const requestContext = args.context ?? Context3.default(void 0, {
997
1167
  F: __dxlog_file6,
998
- L: 293
1168
+ L: 400
999
1169
  });
1000
1170
  log4("fetch", {
1001
1171
  url,
1002
1172
  request: args.body
1003
1173
  }, {
1004
1174
  F: __dxlog_file6,
1005
- L: 294,
1175
+ L: 401,
1006
1176
  S: this,
1007
1177
  C: (f, a) => f(...a)
1008
1178
  });
1009
1179
  let handledAuth = false;
1180
+ const tryCount = 1;
1010
1181
  while (true) {
1011
- let processingError;
1012
- let retryAfterHeaderValue = Number.NaN;
1182
+ let processingError = void 0;
1013
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
+ }
1014
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
+ });
1015
1201
  const response = await fetch(url, request);
1016
- retryAfterHeaderValue = Number(response.headers.get("Retry-After"));
1017
1202
  if (response.ok) {
1018
- const body = await response.json();
1019
- if (body.success) {
1020
- return body.data;
1203
+ const body2 = await response.clone().json();
1204
+ if (args.rawResponse) {
1205
+ return body2;
1021
1206
  }
1022
- log4.warn("unsuccessful edge response", {
1023
- url,
1024
- body
1025
- }, {
1207
+ invariant4(body2, "Expected body to be present", {
1026
1208
  F: __dxlog_file6,
1027
- L: 310,
1209
+ L: 424,
1028
1210
  S: this,
1029
- C: (f, a) => f(...a)
1211
+ A: [
1212
+ "body",
1213
+ "'Expected body to be present'"
1214
+ ]
1030
1215
  });
1031
- if (body.errorData?.type === "auth_challenge" && typeof body.errorData?.challenge === "string") {
1032
- processingError = new EdgeAuthChallengeError(body.errorData.challenge, body.errorData);
1033
- } else {
1034
- processingError = EdgeCallFailedError.fromUnsuccessfulResponse(response, body);
1216
+ if (!("success" in body2)) {
1217
+ return body2;
1218
+ }
1219
+ if (body2.success) {
1220
+ return body2.data;
1035
1221
  }
1036
1222
  } else if (response.status === 401 && !handledAuth) {
1037
1223
  this._authHeader = await this._handleUnauthorized(response);
1038
1224
  handledAuth = true;
1039
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);
1040
1241
  } else {
1041
- 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);
1042
1252
  }
1043
1253
  } catch (error) {
1044
1254
  processingError = EdgeCallFailedError.fromProcessingFailureCause(error);
1045
1255
  }
1046
- if (processingError.isRetryable && await shouldRetry(requestContext, retryAfterHeaderValue)) {
1047
- log4("retrying edge request", {
1256
+ if (processingError?.isRetryable && await shouldRetry(requestContext, processingError.retryAfterMs)) {
1257
+ log4.verbose("retrying edge request", {
1048
1258
  url,
1049
1259
  processingError
1050
1260
  }, {
1051
1261
  F: __dxlog_file6,
1052
- L: 328,
1262
+ L: 455,
1053
1263
  S: this,
1054
1264
  C: (f, a) => f(...a)
1055
1265
  });
@@ -1062,33 +1272,52 @@ var EdgeHttpClient = class {
1062
1272
  if (!this._edgeIdentity) {
1063
1273
  log4.warn("unauthorized response received before identity was set", void 0, {
1064
1274
  F: __dxlog_file6,
1065
- L: 337,
1275
+ L: 464,
1066
1276
  S: this,
1067
1277
  C: (f, a) => f(...a)
1068
1278
  });
1069
- throw EdgeCallFailedError.fromHttpFailure(response);
1279
+ throw await EdgeCallFailedError.fromHttpFailure(response);
1070
1280
  }
1071
1281
  const challenge = await handleAuthChallenge(response, this._edgeIdentity);
1072
1282
  return encodeAuthHeader(challenge);
1073
1283
  }
1074
1284
  };
1075
- 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
+ }
1076
1307
  return {
1077
1308
  method,
1078
- body: body && JSON.stringify(body),
1079
- headers: authHeader ? {
1080
- Authorization: authHeader
1081
- } : void 0
1309
+ body: requestBody,
1310
+ headers
1082
1311
  };
1083
1312
  };
1084
- var createRetryHandler = ({ retry }) => {
1085
- if (!retry || retry.count < 1) {
1313
+ var createRetryHandler = ({ retry: retry2 }) => {
1314
+ if (!retry2 || retry2.count < 1) {
1086
1315
  return async () => false;
1087
1316
  }
1088
1317
  let retries = 0;
1089
- const maxRetries = retry.count ?? DEFAULT_MAX_RETRIES_COUNT;
1090
- const baseTimeout = retry.timeout ?? DEFAULT_RETRY_TIMEOUT;
1091
- 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;
1092
1321
  return async (ctx, retryAfter) => {
1093
1322
  if (++retries > maxRetries || ctx.disposed) {
1094
1323
  return false;
@@ -1096,12 +1325,16 @@ var createRetryHandler = ({ retry }) => {
1096
1325
  if (retryAfter) {
1097
1326
  await sleep(retryAfter);
1098
1327
  } else {
1099
- const timeout = baseTimeout + Math.random() * jitter;
1100
- await sleep(timeout);
1328
+ const timeout2 = baseTimeout + Math.random() * jitter;
1329
+ await sleep(timeout2);
1101
1330
  }
1102
1331
  return true;
1103
1332
  };
1104
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";
1105
1338
  export {
1106
1339
  CLOUDFLARE_MESSAGE_MAX_BYTES,
1107
1340
  CLOUDFLARE_RPC_MAX_BYTES,
@@ -1109,6 +1342,7 @@ export {
1109
1342
  EdgeConnectionClosedError,
1110
1343
  EdgeHttpClient,
1111
1344
  EdgeIdentityChangedError,
1345
+ HttpConfig,
1112
1346
  Protocol,
1113
1347
  WebSocketMuxer,
1114
1348
  createChainEdgeIdentity,
@@ -1116,9 +1350,13 @@ export {
1116
1350
  createEphemeralEdgeIdentity,
1117
1351
  createStubEdgeIdentity,
1118
1352
  createTestHaloEdgeIdentity,
1353
+ encodeAuthHeader,
1119
1354
  getTypename,
1120
1355
  handleAuthChallenge,
1121
1356
  protocol,
1122
- toUint8Array
1357
+ toUint8Array,
1358
+ withLogging,
1359
+ withRetry,
1360
+ withRetryConfig
1123
1361
  };
1124
1362
  //# sourceMappingURL=index.mjs.map