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