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