@dxos/edge-client 0.8.4-main.84f28bd → 0.8.4-main.ae835ea

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