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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist/lib/browser/{chunk-LMP5TVOP.mjs → chunk-VESGVCLQ.mjs} +8 -4
  2. package/dist/lib/browser/{chunk-LMP5TVOP.mjs.map → chunk-VESGVCLQ.mjs.map} +3 -3
  3. package/dist/lib/browser/edge-ws-muxer.mjs +1 -1
  4. package/dist/lib/browser/index.mjs +557 -284
  5. package/dist/lib/browser/index.mjs.map +4 -4
  6. package/dist/lib/browser/meta.json +1 -1
  7. package/dist/lib/browser/testing/index.mjs +1 -1
  8. package/dist/lib/browser/testing/index.mjs.map +2 -2
  9. package/dist/lib/node-esm/{chunk-X7J46ISZ.mjs → chunk-JTBFRYNM.mjs} +8 -4
  10. package/dist/lib/node-esm/{chunk-X7J46ISZ.mjs.map → chunk-JTBFRYNM.mjs.map} +3 -3
  11. package/dist/lib/node-esm/edge-ws-muxer.mjs +1 -1
  12. package/dist/lib/node-esm/index.mjs +557 -284
  13. package/dist/lib/node-esm/index.mjs.map +4 -4
  14. package/dist/lib/node-esm/meta.json +1 -1
  15. package/dist/lib/node-esm/testing/index.mjs +1 -1
  16. package/dist/lib/node-esm/testing/index.mjs.map +2 -2
  17. package/dist/types/src/edge-client.d.ts +15 -15
  18. package/dist/types/src/edge-client.d.ts.map +1 -1
  19. package/dist/types/src/edge-http-client.d.ts +30 -3
  20. package/dist/types/src/edge-http-client.d.ts.map +1 -1
  21. package/dist/types/src/edge-ws-connection.d.ts +20 -0
  22. package/dist/types/src/edge-ws-connection.d.ts.map +1 -1
  23. package/dist/types/src/edge-ws-muxer.d.ts.map +1 -1
  24. package/dist/types/src/http-client.d.ts +10 -7
  25. package/dist/types/src/http-client.d.ts.map +1 -1
  26. package/dist/types/src/index.d.ts +4 -3
  27. package/dist/types/src/index.d.ts.map +1 -1
  28. package/dist/types/src/testing/test-utils.d.ts +1 -1
  29. package/dist/types/src/testing/test-utils.d.ts.map +1 -1
  30. package/dist/types/tsconfig.tsbuildinfo +1 -1
  31. package/package.json +18 -15
  32. package/src/edge-client.test.ts +4 -4
  33. package/src/edge-client.ts +73 -42
  34. package/src/edge-http-client.test.ts +1 -1
  35. package/src/edge-http-client.ts +194 -35
  36. package/src/edge-ws-connection.ts +129 -8
  37. package/src/edge-ws-muxer.ts +1 -1
  38. package/src/http-client.test.ts +8 -6
  39. package/src/http-client.ts +18 -8
  40. package/src/index.ts +4 -3
  41. package/src/testing/test-utils.ts +4 -4
  42. package/src/websocket.test.ts +1 -1
@@ -7,24 +7,135 @@ import {
7
7
  getTypename,
8
8
  protocol,
9
9
  toUint8Array
10
- } from "./chunk-X7J46ISZ.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 { Trigger, scheduleMicroTask, TriggerState, PersistentLifecycle, Event } 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,10 +184,29 @@ 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 {
191
+ _identity;
192
+ _connectionInfo;
193
+ _callbacks;
194
+ _inactivityTimeoutCtx;
195
+ _ws;
196
+ _wsMuxer;
197
+ _lastReceivedMessageTimestamp = Date.now();
198
+ _openTimestamp;
199
+ // Latency tracking.
200
+ _pingTimestamp;
201
+ _rtt = 0;
202
+ // Rate tracking with sliding window.
203
+ _uploadRate = 0;
204
+ _downloadRate = 0;
205
+ _rateWindow = 1e4;
206
+ _rateUpdateInterval = 1e3;
207
+ _bytesSamples = [];
208
+ _messagesSent = 0;
209
+ _messagesReceived = 0;
80
210
  constructor(_identity, _connectionInfo, _callbacks) {
81
211
  super(), this._identity = _identity, this._connectionInfo = _connectionInfo, this._callbacks = _callbacks;
82
212
  }
@@ -87,19 +217,37 @@ var EdgeWsConnection = class extends Resource {
87
217
  device: this._identity.peerKey
88
218
  };
89
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
+ }
90
238
  send(message) {
91
- invariant2(this._ws, void 0, {
92
- F: __dxlog_file2,
93
- L: 52,
239
+ invariant3(this._ws, void 0, {
240
+ F: __dxlog_file3,
241
+ L: 93,
94
242
  S: this,
95
243
  A: [
96
244
  "this._ws",
97
245
  ""
98
246
  ]
99
247
  });
100
- invariant2(this._wsMuxer, void 0, {
101
- F: __dxlog_file2,
102
- L: 53,
248
+ invariant3(this._wsMuxer, void 0, {
249
+ F: __dxlog_file3,
250
+ L: 94,
103
251
  S: this,
104
252
  A: [
105
253
  "this._wsMuxer",
@@ -110,11 +258,12 @@ var EdgeWsConnection = class extends Resource {
110
258
  peerKey: this._identity.peerKey,
111
259
  payload: protocol.getPayloadType(message)
112
260
  }, {
113
- F: __dxlog_file2,
114
- L: 54,
261
+ F: __dxlog_file3,
262
+ L: 95,
115
263
  S: this,
116
264
  C: (f, a) => f(...a)
117
265
  });
266
+ this._messagesSent++;
118
267
  if (this._ws?.protocol.includes(EdgeWebsocketProtocol.V0)) {
119
268
  const binary = buf.toBinary(MessageSchema, message);
120
269
  if (binary.length > CLOUDFLARE_MESSAGE_MAX_BYTES) {
@@ -123,18 +272,21 @@ var EdgeWsConnection = class extends Resource {
123
272
  serviceId: message.serviceId,
124
273
  payload: protocol.getPayloadType(message)
125
274
  }, {
126
- F: __dxlog_file2,
127
- L: 58,
275
+ F: __dxlog_file3,
276
+ L: 100,
128
277
  S: this,
129
278
  C: (f, a) => f(...a)
130
279
  });
131
280
  return;
132
281
  }
282
+ this._recordBytes(binary.byteLength, 0);
133
283
  this._ws.send(binary);
134
284
  } else {
285
+ const binary = buf.toBinary(MessageSchema, message);
286
+ this._recordBytes(binary.byteLength, 0);
135
287
  this._wsMuxer.send(message).catch((e) => log.catch(e, void 0, {
136
- F: __dxlog_file2,
137
- L: 67,
288
+ F: __dxlog_file3,
289
+ L: 113,
138
290
  S: this,
139
291
  C: (f, a) => f(...a)
140
292
  }));
@@ -155,19 +307,21 @@ var EdgeWsConnection = class extends Resource {
155
307
  this._ws.onopen = () => {
156
308
  if (this.isOpen) {
157
309
  log("connected", void 0, {
158
- F: __dxlog_file2,
159
- L: 84,
310
+ F: __dxlog_file3,
311
+ L: 130,
160
312
  S: this,
161
313
  C: (f, a) => f(...a)
162
314
  });
315
+ this._openTimestamp = Date.now();
163
316
  this._callbacks.onConnected();
164
317
  this._scheduleHeartbeats();
318
+ this._scheduleRateCalculation();
165
319
  } else {
166
320
  log.verbose("connected after becoming inactive", {
167
321
  currentIdentity: this._identity
168
322
  }, {
169
- F: __dxlog_file2,
170
- L: 88,
323
+ F: __dxlog_file3,
324
+ L: 136,
171
325
  S: this,
172
326
  C: (f, a) => f(...a)
173
327
  });
@@ -175,12 +329,12 @@ var EdgeWsConnection = class extends Resource {
175
329
  };
176
330
  this._ws.onclose = (event) => {
177
331
  if (this.isOpen) {
178
- log.warn("disconnected while being open", {
332
+ log.warn("server disconnected", {
179
333
  code: event.code,
180
334
  reason: event.reason
181
335
  }, {
182
- F: __dxlog_file2,
183
- L: 93,
336
+ F: __dxlog_file3,
337
+ L: 141,
184
338
  S: this,
185
339
  C: (f, a) => f(...a)
186
340
  });
@@ -194,8 +348,8 @@ var EdgeWsConnection = class extends Resource {
194
348
  error: event.error,
195
349
  info: event.message
196
350
  }, {
197
- F: __dxlog_file2,
198
- L: 100,
351
+ F: __dxlog_file3,
352
+ L: 148,
199
353
  S: this,
200
354
  C: (f, a) => f(...a)
201
355
  });
@@ -204,8 +358,8 @@ var EdgeWsConnection = class extends Resource {
204
358
  log.verbose("error ignored on closed connection", {
205
359
  error: event.error
206
360
  }, {
207
- F: __dxlog_file2,
208
- L: 103,
361
+ F: __dxlog_file3,
362
+ L: 151,
209
363
  S: this,
210
364
  C: (f, a) => f(...a)
211
365
  });
@@ -216,29 +370,36 @@ var EdgeWsConnection = class extends Resource {
216
370
  log.verbose("message ignored on closed connection", {
217
371
  event: event.type
218
372
  }, {
219
- F: __dxlog_file2,
220
- L: 111,
373
+ F: __dxlog_file3,
374
+ L: 159,
221
375
  S: this,
222
376
  C: (f, a) => f(...a)
223
377
  });
224
378
  return;
225
379
  }
380
+ this._lastReceivedMessageTimestamp = Date.now();
226
381
  if (event.data === "__pong__") {
382
+ if (this._pingTimestamp) {
383
+ this._rtt = Date.now() - this._pingTimestamp;
384
+ this._pingTimestamp = void 0;
385
+ }
227
386
  this._rescheduleHeartbeatTimeout();
228
387
  return;
229
388
  }
230
389
  const bytes = await toUint8Array(event.data);
390
+ this._recordBytes(0, bytes.byteLength);
231
391
  if (!this.isOpen) {
232
392
  return;
233
393
  }
394
+ this._messagesReceived++;
234
395
  const message = this._ws?.protocol?.includes(EdgeWebsocketProtocol.V0) ? buf.fromBinary(MessageSchema, bytes) : muxer.receiveData(bytes);
235
396
  if (message) {
236
397
  log("received", {
237
398
  from: message.source,
238
399
  payload: protocol.getPayloadType(message)
239
400
  }, {
240
- F: __dxlog_file2,
241
- L: 128,
401
+ F: __dxlog_file3,
402
+ L: 185,
242
403
  S: this,
243
404
  C: (f, a) => f(...a)
244
405
  });
@@ -258,20 +419,20 @@ var EdgeWsConnection = class extends Resource {
258
419
  if (err instanceof Error && err.message.includes("WebSocket is closed before the connection is established.")) {
259
420
  return;
260
421
  }
261
- log.warn("Error closing websocket", {
422
+ log.warn("error closing websocket", {
262
423
  err
263
424
  }, {
264
- F: __dxlog_file2,
265
- L: 146,
425
+ F: __dxlog_file3,
426
+ L: 203,
266
427
  S: this,
267
428
  C: (f, a) => f(...a)
268
429
  });
269
430
  }
270
431
  }
271
432
  _scheduleHeartbeats() {
272
- invariant2(this._ws, void 0, {
273
- F: __dxlog_file2,
274
- L: 151,
433
+ invariant3(this._ws, void 0, {
434
+ F: __dxlog_file3,
435
+ L: 208,
275
436
  S: this,
276
437
  A: [
277
438
  "this._ws",
@@ -279,8 +440,10 @@ var EdgeWsConnection = class extends Resource {
279
440
  ]
280
441
  });
281
442
  scheduleTaskInterval(this._ctx, async () => {
443
+ this._pingTimestamp = Date.now();
282
444
  this._ws?.send("__ping__");
283
445
  }, SIGNAL_KEEPALIVE_INTERVAL);
446
+ this._pingTimestamp = Date.now();
284
447
  this._ws.send("__ping__");
285
448
  this._rescheduleHeartbeatTimeout();
286
449
  }
@@ -290,21 +453,68 @@ var EdgeWsConnection = class extends Resource {
290
453
  }
291
454
  void this._inactivityTimeoutCtx?.dispose();
292
455
  this._inactivityTimeoutCtx = new Context(void 0, {
293
- F: __dxlog_file2,
294
- L: 170
456
+ F: __dxlog_file3,
457
+ L: 229
295
458
  });
296
459
  scheduleTask(this._inactivityTimeoutCtx, () => {
297
460
  if (this.isOpen) {
298
- log.warn("restart due to inactivity timeout", void 0, {
299
- F: __dxlog_file2,
300
- L: 175,
301
- S: this,
302
- C: (f, a) => f(...a)
303
- });
304
- this._callbacks.onRestartRequired();
461
+ if (Date.now() - this._lastReceivedMessageTimestamp > SIGNAL_KEEPALIVE_TIMEOUT) {
462
+ log.warn("restart due to inactivity timeout", {
463
+ lastReceivedMessageTimestamp: this._lastReceivedMessageTimestamp
464
+ }, {
465
+ F: __dxlog_file3,
466
+ L: 235,
467
+ S: this,
468
+ C: (f, a) => f(...a)
469
+ });
470
+ this._callbacks.onRestartRequired();
471
+ } else {
472
+ this._rescheduleHeartbeatTimeout();
473
+ }
305
474
  }
306
475
  }, SIGNAL_KEEPALIVE_TIMEOUT);
307
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
+ }
308
518
  };
309
519
  _ts_decorate([
310
520
  logInfo
@@ -337,14 +547,25 @@ function _ts_decorate2(decorators, target, key, desc) {
337
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;
338
548
  return c > 3 && r && Object.defineProperty(target, key, r), r;
339
549
  }
340
- 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";
341
551
  var DEFAULT_TIMEOUT = 1e4;
552
+ var STATUS_REFRESH_INTERVAL = 1e3;
342
553
  var EdgeClient = class extends Resource2 {
554
+ _identity;
555
+ _config;
556
+ statusChanged = new Event();
557
+ _persistentLifecycle = new PersistentLifecycle({
558
+ start: async () => this._connect(),
559
+ stop: async (state) => this._disconnect(state)
560
+ });
561
+ _messageListeners = /* @__PURE__ */ new Set();
562
+ _reconnectListeners = /* @__PURE__ */ new Set();
563
+ _baseWsUrl;
564
+ _baseHttpUrl;
565
+ _currentConnection = void 0;
566
+ _ready = new Trigger();
343
567
  constructor(_identity, _config) {
344
- super(), this._identity = _identity, this._config = _config, this.statusChanged = new Event(), this._persistentLifecycle = new PersistentLifecycle({
345
- start: async () => this._connect(),
346
- stop: async (state) => this._disconnect(state)
347
- }), 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;
348
569
  this._baseWsUrl = getEdgeUrlWithProtocol(_config.socketEndpoint, "ws");
349
570
  this._baseHttpUrl = getEdgeUrlWithProtocol(_config.socketEndpoint, "http");
350
571
  }
@@ -357,7 +578,15 @@ var EdgeClient = class extends Resource2 {
357
578
  };
358
579
  }
359
580
  get status() {
360
- 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
+ };
361
590
  }
362
591
  get identityKey() {
363
592
  return this._identity.identityKey;
@@ -371,8 +600,8 @@ var EdgeClient = class extends Resource2 {
371
600
  identity,
372
601
  oldIdentity: this._identity
373
602
  }, {
374
- F: __dxlog_file3,
375
- L: 99,
603
+ F: __dxlog_file4,
604
+ L: 118,
376
605
  S: this,
377
606
  C: (f, a) => f(...a)
378
607
  });
@@ -381,6 +610,30 @@ var EdgeClient = class extends Resource2 {
381
610
  void this._persistentLifecycle.scheduleRestart();
382
611
  }
383
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
+ }
384
637
  onMessage(listener) {
385
638
  this._messageListeners.add(listener);
386
639
  return () => this._messageListeners.delete(listener);
@@ -394,8 +647,8 @@ var EdgeClient = class extends Resource2 {
394
647
  listener();
395
648
  } catch (error) {
396
649
  log2.catch(error, void 0, {
397
- F: __dxlog_file3,
398
- L: 121,
650
+ F: __dxlog_file4,
651
+ L: 164,
399
652
  S: this,
400
653
  C: (f, a) => f(...a)
401
654
  });
@@ -412,8 +665,8 @@ var EdgeClient = class extends Resource2 {
412
665
  log2("opening...", {
413
666
  info: this.info
414
667
  }, {
415
- F: __dxlog_file3,
416
- L: 133,
668
+ F: __dxlog_file4,
669
+ L: 177,
417
670
  S: this,
418
671
  C: (f, a) => f(...a)
419
672
  });
@@ -421,12 +674,18 @@ var EdgeClient = class extends Resource2 {
421
674
  log2.warn("Error while opening connection", {
422
675
  err
423
676
  }, {
424
- F: __dxlog_file3,
425
- L: 135,
677
+ F: __dxlog_file4,
678
+ L: 179,
426
679
  S: this,
427
680
  C: (f, a) => f(...a)
428
681
  });
429
682
  });
683
+ scheduleTaskInterval2(this._ctx, async () => {
684
+ if (!this._currentConnection) {
685
+ return;
686
+ }
687
+ this.statusChanged.emit(this.status);
688
+ }, STATUS_REFRESH_INTERVAL);
430
689
  }
431
690
  /**
432
691
  * Close connection and free resources.
@@ -435,8 +694,8 @@ var EdgeClient = class extends Resource2 {
435
694
  log2("closing...", {
436
695
  peerKey: this._identity.peerKey
437
696
  }, {
438
- F: __dxlog_file3,
439
- L: 143,
697
+ F: __dxlog_file4,
698
+ L: 199,
440
699
  S: this,
441
700
  C: (f, a) => f(...a)
442
701
  });
@@ -452,8 +711,8 @@ var EdgeClient = class extends Resource2 {
452
711
  const protocolHeader = this._config.disableAuth ? void 0 : await this._createAuthHeader(path);
453
712
  if (this._identity !== identity) {
454
713
  log2("identity changed during auth header request", void 0, {
455
- F: __dxlog_file3,
456
- L: 157,
714
+ F: __dxlog_file4,
715
+ L: 213,
457
716
  S: this,
458
717
  C: (f, a) => f(...a)
459
718
  });
@@ -465,8 +724,8 @@ var EdgeClient = class extends Resource2 {
465
724
  url: url.toString(),
466
725
  protocolHeader
467
726
  }, {
468
- F: __dxlog_file3,
469
- L: 163,
727
+ F: __dxlog_file4,
728
+ L: 219,
470
729
  S: this,
471
730
  C: (f, a) => f(...a)
472
731
  });
@@ -480,8 +739,8 @@ var EdgeClient = class extends Resource2 {
480
739
  this._notifyReconnected();
481
740
  } else {
482
741
  log2.verbose("connected callback ignored, because connection is not active", void 0, {
483
- F: __dxlog_file3,
484
- L: 173,
742
+ F: __dxlog_file4,
743
+ L: 229,
485
744
  S: this,
486
745
  C: (f, a) => f(...a)
487
746
  });
@@ -493,8 +752,8 @@ var EdgeClient = class extends Resource2 {
493
752
  void this._persistentLifecycle.scheduleRestart();
494
753
  } else {
495
754
  log2.verbose("restart requested by inactive connection", void 0, {
496
- F: __dxlog_file3,
497
- L: 181,
755
+ F: __dxlog_file4,
756
+ L: 237,
498
757
  S: this,
499
758
  C: (f, a) => f(...a)
500
759
  });
@@ -509,8 +768,8 @@ var EdgeClient = class extends Resource2 {
509
768
  from: message.source,
510
769
  type: message.payload?.typeUrl
511
770
  }, {
512
- F: __dxlog_file3,
513
- L: 189,
771
+ F: __dxlog_file4,
772
+ L: 245,
514
773
  S: this,
515
774
  C: (f, a) => f(...a)
516
775
  });
@@ -546,8 +805,8 @@ var EdgeClient = class extends Resource2 {
546
805
  log2.error("ws reconnect listener failed", {
547
806
  err
548
807
  }, {
549
- F: __dxlog_file3,
550
- L: 225,
808
+ F: __dxlog_file4,
809
+ L: 280,
551
810
  S: this,
552
811
  C: (f, a) => f(...a)
553
812
  });
@@ -563,38 +822,14 @@ var EdgeClient = class extends Resource2 {
563
822
  err,
564
823
  payload: protocol.getPayloadType(message)
565
824
  }, {
566
- F: __dxlog_file3,
567
- L: 235,
825
+ F: __dxlog_file4,
826
+ L: 290,
568
827
  S: this,
569
828
  C: (f, a) => f(...a)
570
829
  });
571
830
  }
572
831
  }
573
832
  }
574
- /**
575
- * Send message.
576
- * NOTE: The message is guaranteed to be delivered but the service must respond with a message to confirm processing.
577
- */
578
- async send(message) {
579
- if (this._ready.state !== TriggerState.RESOLVED) {
580
- log2("waiting for websocket to become ready", void 0, {
581
- F: __dxlog_file3,
582
- L: 246,
583
- S: this,
584
- C: (f, a) => f(...a)
585
- });
586
- await this._ready.wait({
587
- timeout: this._config.timeout ?? DEFAULT_TIMEOUT
588
- });
589
- }
590
- if (!this._currentConnection) {
591
- throw new EdgeConnectionClosedError();
592
- }
593
- if (message.source && (message.source.peerKey !== this._identity.peerKey || message.source.identityKey !== this.identityKey)) {
594
- throw new EdgeIdentityChangedError();
595
- }
596
- this._currentConnection.send(message);
597
- }
598
833
  async _createAuthHeader(path) {
599
834
  const httpUrl = new URL(path, this._baseHttpUrl);
600
835
  httpUrl.protocol = getEdgeUrlWithProtocol(this._baseWsUrl.toString(), "http");
@@ -608,14 +843,15 @@ var EdgeClient = class extends Resource2 {
608
843
  status: response.status,
609
844
  statusText: response.statusText
610
845
  }, {
611
- F: __dxlog_file3,
612
- L: 271,
846
+ F: __dxlog_file4,
847
+ L: 302,
613
848
  S: this,
614
849
  C: (f, a) => f(...a)
615
850
  });
616
851
  return void 0;
617
852
  }
618
853
  }
854
+ _isActive = (connection) => connection === this._currentConnection;
619
855
  };
620
856
  _ts_decorate2([
621
857
  logInfo2
@@ -625,144 +861,38 @@ var encodePresentationWsAuthHeader = (encodedPresentation) => {
625
861
  return `base64url.bearer.authorization.dxos.org.${encodedToken}`;
626
862
  };
627
863
 
628
- // src/auth.ts
629
- import { createCredential, signPresentation } from "@dxos/credentials";
630
- import { invariant as invariant3 } from "@dxos/invariant";
631
- import { Keyring } from "@dxos/keyring";
632
- import { PublicKey } from "@dxos/keys";
633
- var __dxlog_file4 = "/__w/dxos/dxos/packages/core/mesh/edge-client/src/auth.ts";
634
- var createDeviceEdgeIdentity = async (signer, key) => {
635
- return {
636
- identityKey: key.toHex(),
637
- peerKey: key.toHex(),
638
- presentCredentials: async ({ challenge }) => {
639
- return signPresentation({
640
- presentation: {
641
- credentials: [
642
- // Verifier requires at least one credential in the presentation to establish the subject.
643
- await createCredential({
644
- assertion: {
645
- "@type": "dxos.halo.credentials.Auth"
646
- },
647
- issuer: key,
648
- subject: key,
649
- signer
650
- })
651
- ]
652
- },
653
- signer,
654
- signerKey: key,
655
- nonce: challenge
656
- });
657
- }
658
- };
659
- };
660
- var createChainEdgeIdentity = async (signer, identityKey, peerKey, chain, credentials) => {
661
- const credentialsToSign = credentials.length > 0 ? credentials : [
662
- await createCredential({
663
- assertion: {
664
- "@type": "dxos.halo.credentials.Auth"
665
- },
666
- issuer: identityKey,
667
- subject: identityKey,
668
- signer,
669
- chain,
670
- signingKey: peerKey
671
- })
672
- ];
673
- return {
674
- identityKey: identityKey.toHex(),
675
- peerKey: peerKey.toHex(),
676
- presentCredentials: async ({ challenge }) => {
677
- invariant3(chain, void 0, {
678
- F: __dxlog_file4,
679
- L: 75,
680
- S: void 0,
681
- A: [
682
- "chain",
683
- ""
684
- ]
685
- });
686
- return signPresentation({
687
- presentation: {
688
- credentials: credentialsToSign
689
- },
690
- signer,
691
- nonce: challenge,
692
- signerKey: peerKey,
693
- chain
694
- });
695
- }
696
- };
697
- };
698
- var createEphemeralEdgeIdentity = async () => {
699
- const keyring = new Keyring();
700
- const key = await keyring.createKey();
701
- return createDeviceEdgeIdentity(keyring, key);
702
- };
703
- var createTestHaloEdgeIdentity = async (signer, identityKey, deviceKey) => {
704
- const deviceAdmission = await createCredential({
705
- assertion: {
706
- "@type": "dxos.halo.credentials.AuthorizedDevice",
707
- deviceKey,
708
- identityKey
709
- },
710
- issuer: identityKey,
711
- subject: deviceKey,
712
- signer
713
- });
714
- return createChainEdgeIdentity(signer, identityKey, deviceKey, {
715
- credential: deviceAdmission
716
- }, [
717
- await createCredential({
718
- assertion: {
719
- "@type": "dxos.halo.credentials.Auth"
720
- },
721
- issuer: identityKey,
722
- subject: identityKey,
723
- signer
724
- })
725
- ]);
726
- };
727
- var createStubEdgeIdentity = () => {
728
- const identityKey = PublicKey.random();
729
- const deviceKey = PublicKey.random();
730
- return {
731
- identityKey: identityKey.toHex(),
732
- peerKey: deviceKey.toHex(),
733
- presentCredentials: async () => {
734
- throw new Error("Stub identity does not support authentication.");
735
- }
736
- };
737
- };
738
-
739
864
  // src/edge-http-client.ts
740
- import { FetchHttpClient, HttpClient } from "@effect/platform";
741
- 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";
742
869
  import { sleep } from "@dxos/async";
743
870
  import { Context as Context3 } from "@dxos/context";
871
+ import { invariant as invariant4 } from "@dxos/invariant";
744
872
  import { log as log4 } from "@dxos/log";
745
873
  import { EdgeAuthChallengeError, EdgeCallFailedError } from "@dxos/protocols";
746
874
  import { createUrl } from "@dxos/util";
747
875
 
748
876
  // src/http-client.ts
749
- 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";
750
882
  import { log as log3 } from "@dxos/log";
751
883
  var __dxlog_file5 = "/__w/dxos/dxos/packages/core/mesh/edge-client/src/http-client.ts";
752
884
  var HttpConfig = class _HttpConfig extends Context2.Tag("HttpConfig")() {
753
- static {
754
- this.default = Layer.succeed(_HttpConfig, {
755
- timeout: Duration.millis(1e3),
756
- retryTimes: 3,
757
- retryBaseDelay: Duration.millis(1e3)
758
- });
759
- }
885
+ static default = Layer.succeed(_HttpConfig, {
886
+ timeout: Duration.millis(1e3),
887
+ retryTimes: 3,
888
+ retryBaseDelay: Duration.millis(1e3)
889
+ });
760
890
  };
761
- 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 } = {}) => {
762
892
  return effect.pipe(Effect.flatMap((res) => (
763
893
  // Treat 500 errors as retryable?
764
894
  res.status === 500 ? Effect.fail(new Error(res.status.toString())) : res.json
765
- )), Effect.timeout(timeout), Effect.retry({
895
+ )), Effect.timeout(timeout2), Effect.retry({
766
896
  schedule: Schedule.exponential(retryBaseDelay).pipe(Schedule.jittered),
767
897
  times: retryTimes
768
898
  }));
@@ -771,14 +901,16 @@ var withRetryConfig = (effect) => Effect.gen(function* () {
771
901
  const config = yield* HttpConfig;
772
902
  return yield* withRetry(effect, config);
773
903
  });
774
- var withLogging = (effect) => effect.pipe(Effect.tap((res) => log3.info("response", {
775
- status: res.status
776
- }, {
777
- F: __dxlog_file5,
778
- L: 58,
779
- S: void 0,
780
- C: (f, a) => f(...a)
781
- })));
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
+ }));
782
914
  var encodeAuthHeader = (challenge) => {
783
915
  const encodedChallenge = Buffer.from(challenge).toString("base64");
784
916
  return `VerifiablePresentation pb;base64,${encodedChallenge}`;
@@ -789,14 +921,21 @@ var __dxlog_file6 = "/__w/dxos/dxos/packages/core/mesh/edge-client/src/edge-http
789
921
  var DEFAULT_RETRY_TIMEOUT = 1500;
790
922
  var DEFAULT_RETRY_JITTER = 500;
791
923
  var DEFAULT_MAX_RETRIES_COUNT = 3;
924
+ var WARNING_BODY_SIZE = 10 * 1024 * 1024;
792
925
  var EdgeHttpClient = class {
926
+ _baseUrl;
927
+ _edgeIdentity;
928
+ /**
929
+ * Auth header is cached until receiving the next 401 from EDGE, at which point it gets refreshed.
930
+ */
931
+ _authHeader;
793
932
  constructor(baseUrl) {
794
933
  this._baseUrl = getEdgeUrlWithProtocol(baseUrl, "http");
795
934
  log4("created", {
796
935
  url: this._baseUrl
797
936
  }, {
798
937
  F: __dxlog_file6,
799
- L: 84,
938
+ L: 107,
800
939
  S: this,
801
940
  C: (f, a) => f(...a)
802
941
  });
@@ -928,6 +1067,19 @@ var EdgeHttpClient = class {
928
1067
  // Functions
929
1068
  //
930
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
+ }
931
1083
  const path = [
932
1084
  "functions",
933
1085
  ...pathParts.functionId ? [
@@ -936,8 +1088,36 @@ var EdgeHttpClient = class {
936
1088
  ].join("/");
937
1089
  return this._call(new URL(path, this.baseUrl), {
938
1090
  ...args,
939
- body,
940
- 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
941
1121
  });
942
1122
  }
943
1123
  //
@@ -951,71 +1131,136 @@ var EdgeHttpClient = class {
951
1131
  });
952
1132
  }
953
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
+ //
954
1159
  // Internal
955
1160
  //
956
- async _fetch(url, args) {
957
- 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);
958
1163
  }
959
1164
  // TODO(burdon): Refactor with effect (see edge-http-client.test.ts).
960
1165
  async _call(url, args) {
961
1166
  const shouldRetry = createRetryHandler(args);
962
- const requestContext = args.context ?? new Context3(void 0, {
1167
+ const requestContext = args.context ?? Context3.default(void 0, {
963
1168
  F: __dxlog_file6,
964
- L: 289
1169
+ L: 400
965
1170
  });
966
1171
  log4("fetch", {
967
1172
  url,
968
1173
  request: args.body
969
1174
  }, {
970
1175
  F: __dxlog_file6,
971
- L: 290,
1176
+ L: 401,
972
1177
  S: this,
973
1178
  C: (f, a) => f(...a)
974
1179
  });
975
1180
  let handledAuth = false;
1181
+ const tryCount = 1;
976
1182
  while (true) {
977
- let processingError;
978
- let retryAfterHeaderValue = Number.NaN;
1183
+ let processingError = void 0;
979
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
+ }
980
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
+ });
981
1202
  const response = await fetch(url, request);
982
- retryAfterHeaderValue = Number(response.headers.get("Retry-After"));
983
1203
  if (response.ok) {
984
- const body = await response.json();
985
- if (body.success) {
986
- return body.data;
1204
+ const body2 = await response.clone().json();
1205
+ if (args.rawResponse) {
1206
+ return body2;
987
1207
  }
988
- log4.warn("unsuccessful edge response", {
989
- url,
990
- body
991
- }, {
1208
+ invariant4(body2, "Expected body to be present", {
992
1209
  F: __dxlog_file6,
993
- L: 306,
1210
+ L: 424,
994
1211
  S: this,
995
- C: (f, a) => f(...a)
1212
+ A: [
1213
+ "body",
1214
+ "'Expected body to be present'"
1215
+ ]
996
1216
  });
997
- if (body.errorData?.type === "auth_challenge" && typeof body.errorData?.challenge === "string") {
998
- processingError = new EdgeAuthChallengeError(body.errorData.challenge, body.errorData);
999
- } else {
1000
- processingError = EdgeCallFailedError.fromUnsuccessfulResponse(response, body);
1217
+ if (!("success" in body2)) {
1218
+ return body2;
1219
+ }
1220
+ if (body2.success) {
1221
+ return body2.data;
1001
1222
  }
1002
1223
  } else if (response.status === 401 && !handledAuth) {
1003
1224
  this._authHeader = await this._handleUnauthorized(response);
1004
1225
  handledAuth = true;
1005
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);
1006
1242
  } else {
1007
- 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);
1008
1253
  }
1009
1254
  } catch (error) {
1010
1255
  processingError = EdgeCallFailedError.fromProcessingFailureCause(error);
1011
1256
  }
1012
- if (processingError.isRetryable && await shouldRetry(requestContext, retryAfterHeaderValue)) {
1013
- log4("retrying edge request", {
1257
+ if (processingError?.isRetryable && await shouldRetry(requestContext, processingError.retryAfterMs)) {
1258
+ log4.verbose("retrying edge request", {
1014
1259
  url,
1015
1260
  processingError
1016
1261
  }, {
1017
1262
  F: __dxlog_file6,
1018
- L: 324,
1263
+ L: 455,
1019
1264
  S: this,
1020
1265
  C: (f, a) => f(...a)
1021
1266
  });
@@ -1028,33 +1273,52 @@ var EdgeHttpClient = class {
1028
1273
  if (!this._edgeIdentity) {
1029
1274
  log4.warn("unauthorized response received before identity was set", void 0, {
1030
1275
  F: __dxlog_file6,
1031
- L: 333,
1276
+ L: 464,
1032
1277
  S: this,
1033
1278
  C: (f, a) => f(...a)
1034
1279
  });
1035
- throw EdgeCallFailedError.fromHttpFailure(response);
1280
+ throw await EdgeCallFailedError.fromHttpFailure(response);
1036
1281
  }
1037
1282
  const challenge = await handleAuthChallenge(response, this._edgeIdentity);
1038
1283
  return encodeAuthHeader(challenge);
1039
1284
  }
1040
1285
  };
1041
- 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
+ }
1042
1308
  return {
1043
1309
  method,
1044
- body: body && JSON.stringify(body),
1045
- headers: authHeader ? {
1046
- Authorization: authHeader
1047
- } : void 0
1310
+ body: requestBody,
1311
+ headers
1048
1312
  };
1049
1313
  };
1050
- var createRetryHandler = ({ retry }) => {
1051
- if (!retry || retry.count < 1) {
1314
+ var createRetryHandler = ({ retry: retry2 }) => {
1315
+ if (!retry2 || retry2.count < 1) {
1052
1316
  return async () => false;
1053
1317
  }
1054
1318
  let retries = 0;
1055
- const maxRetries = retry.count ?? DEFAULT_MAX_RETRIES_COUNT;
1056
- const baseTimeout = retry.timeout ?? DEFAULT_RETRY_TIMEOUT;
1057
- 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;
1058
1322
  return async (ctx, retryAfter) => {
1059
1323
  if (++retries > maxRetries || ctx.disposed) {
1060
1324
  return false;
@@ -1062,12 +1326,16 @@ var createRetryHandler = ({ retry }) => {
1062
1326
  if (retryAfter) {
1063
1327
  await sleep(retryAfter);
1064
1328
  } else {
1065
- const timeout = baseTimeout + Math.random() * jitter;
1066
- await sleep(timeout);
1329
+ const timeout2 = baseTimeout + Math.random() * jitter;
1330
+ await sleep(timeout2);
1067
1331
  }
1068
1332
  return true;
1069
1333
  };
1070
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";
1071
1339
  export {
1072
1340
  CLOUDFLARE_MESSAGE_MAX_BYTES,
1073
1341
  CLOUDFLARE_RPC_MAX_BYTES,
@@ -1075,6 +1343,7 @@ export {
1075
1343
  EdgeConnectionClosedError,
1076
1344
  EdgeHttpClient,
1077
1345
  EdgeIdentityChangedError,
1346
+ HttpConfig,
1078
1347
  Protocol,
1079
1348
  WebSocketMuxer,
1080
1349
  createChainEdgeIdentity,
@@ -1082,9 +1351,13 @@ export {
1082
1351
  createEphemeralEdgeIdentity,
1083
1352
  createStubEdgeIdentity,
1084
1353
  createTestHaloEdgeIdentity,
1354
+ encodeAuthHeader,
1085
1355
  getTypename,
1086
1356
  handleAuthChallenge,
1087
1357
  protocol,
1088
- toUint8Array
1358
+ toUint8Array,
1359
+ withLogging,
1360
+ withRetry,
1361
+ withRetryConfig
1089
1362
  };
1090
1363
  //# sourceMappingURL=index.mjs.map