@dxos/edge-client 0.8.4-main.f5c0578 → 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-SUXH7FH6.mjs → neutral/chunk-VESGVCLQ.mjs} +4 -7
- package/dist/lib/{browser/chunk-SUXH7FH6.mjs.map → neutral/chunk-VESGVCLQ.mjs.map} +2 -2
- package/dist/lib/{browser → neutral}/edge-ws-muxer.mjs +1 -1
- package/dist/lib/{browser → neutral}/index.mjs +635 -327
- 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/{browser → neutral}/testing/index.mjs.map +2 -2
- package/dist/types/src/edge-client.d.ts +17 -14
- package/dist/types/src/edge-client.d.ts.map +1 -1
- package/dist/types/src/edge-http-client.d.ts +62 -22
- package/dist/types/src/edge-http-client.d.ts.map +1 -1
- package/dist/types/src/edge-ws-connection.d.ts +20 -0
- package/dist/types/src/edge-ws-connection.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 +28 -24
- package/src/edge-client.test.ts +20 -15
- package/src/edge-client.ts +89 -42
- package/src/edge-http-client.test.ts +3 -2
- package/src/edge-http-client.ts +320 -69
- package/src/edge-ws-connection.ts +120 -6
- package/src/http-client.test.ts +11 -7
- package/src/http-client.ts +18 -8
- package/src/index.ts +4 -3
- package/src/testing/test-utils.ts +7 -7
- package/dist/lib/browser/index.mjs.map +0 -7
- package/dist/lib/browser/meta.json +0 -1
- package/dist/lib/node-esm/chunk-R6K4IIBW.mjs +0 -306
- package/dist/lib/node-esm/chunk-R6K4IIBW.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 -1125
- 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/node-esm/testing/index.mjs.map +0 -7
- /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 { Event, PersistentLifecycle, Trigger, TriggerState, scheduleMicroTask } from "@dxos/async";
|
|
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,7 +184,7 @@ 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 {
|
|
@@ -82,9 +194,21 @@ var EdgeWsConnection = class extends Resource {
|
|
|
82
194
|
_inactivityTimeoutCtx;
|
|
83
195
|
_ws;
|
|
84
196
|
_wsMuxer;
|
|
85
|
-
_lastReceivedMessageTimestamp;
|
|
197
|
+
_lastReceivedMessageTimestamp = Date.now();
|
|
198
|
+
_openTimestamp;
|
|
199
|
+
// Latency tracking.
|
|
200
|
+
_pingTimestamp;
|
|
201
|
+
_rtt = 0;
|
|
202
|
+
// Rate tracking with sliding window.
|
|
203
|
+
_uploadRate = 0;
|
|
204
|
+
_downloadRate = 0;
|
|
205
|
+
_rateWindow = 1e4;
|
|
206
|
+
_rateUpdateInterval = 1e3;
|
|
207
|
+
_bytesSamples = [];
|
|
208
|
+
_messagesSent = 0;
|
|
209
|
+
_messagesReceived = 0;
|
|
86
210
|
constructor(_identity, _connectionInfo, _callbacks) {
|
|
87
|
-
super(), this._identity = _identity, this._connectionInfo = _connectionInfo, this._callbacks = _callbacks
|
|
211
|
+
super(), this._identity = _identity, this._connectionInfo = _connectionInfo, this._callbacks = _callbacks;
|
|
88
212
|
}
|
|
89
213
|
get info() {
|
|
90
214
|
return {
|
|
@@ -93,19 +217,37 @@ var EdgeWsConnection = class extends Resource {
|
|
|
93
217
|
device: this._identity.peerKey
|
|
94
218
|
};
|
|
95
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
|
+
}
|
|
96
238
|
send(message) {
|
|
97
|
-
|
|
98
|
-
F:
|
|
99
|
-
L:
|
|
239
|
+
invariant3(this._ws, void 0, {
|
|
240
|
+
F: __dxlog_file3,
|
|
241
|
+
L: 93,
|
|
100
242
|
S: this,
|
|
101
243
|
A: [
|
|
102
244
|
"this._ws",
|
|
103
245
|
""
|
|
104
246
|
]
|
|
105
247
|
});
|
|
106
|
-
|
|
107
|
-
F:
|
|
108
|
-
L:
|
|
248
|
+
invariant3(this._wsMuxer, void 0, {
|
|
249
|
+
F: __dxlog_file3,
|
|
250
|
+
L: 94,
|
|
109
251
|
S: this,
|
|
110
252
|
A: [
|
|
111
253
|
"this._wsMuxer",
|
|
@@ -116,11 +258,12 @@ var EdgeWsConnection = class extends Resource {
|
|
|
116
258
|
peerKey: this._identity.peerKey,
|
|
117
259
|
payload: protocol.getPayloadType(message)
|
|
118
260
|
}, {
|
|
119
|
-
F:
|
|
120
|
-
L:
|
|
261
|
+
F: __dxlog_file3,
|
|
262
|
+
L: 95,
|
|
121
263
|
S: this,
|
|
122
264
|
C: (f, a) => f(...a)
|
|
123
265
|
});
|
|
266
|
+
this._messagesSent++;
|
|
124
267
|
if (this._ws?.protocol.includes(EdgeWebsocketProtocol.V0)) {
|
|
125
268
|
const binary = buf.toBinary(MessageSchema, message);
|
|
126
269
|
if (binary.length > CLOUDFLARE_MESSAGE_MAX_BYTES) {
|
|
@@ -129,18 +272,21 @@ var EdgeWsConnection = class extends Resource {
|
|
|
129
272
|
serviceId: message.serviceId,
|
|
130
273
|
payload: protocol.getPayloadType(message)
|
|
131
274
|
}, {
|
|
132
|
-
F:
|
|
133
|
-
L:
|
|
275
|
+
F: __dxlog_file3,
|
|
276
|
+
L: 100,
|
|
134
277
|
S: this,
|
|
135
278
|
C: (f, a) => f(...a)
|
|
136
279
|
});
|
|
137
280
|
return;
|
|
138
281
|
}
|
|
282
|
+
this._recordBytes(binary.byteLength, 0);
|
|
139
283
|
this._ws.send(binary);
|
|
140
284
|
} else {
|
|
285
|
+
const binary = buf.toBinary(MessageSchema, message);
|
|
286
|
+
this._recordBytes(binary.byteLength, 0);
|
|
141
287
|
this._wsMuxer.send(message).catch((e) => log.catch(e, void 0, {
|
|
142
|
-
F:
|
|
143
|
-
L:
|
|
288
|
+
F: __dxlog_file3,
|
|
289
|
+
L: 113,
|
|
144
290
|
S: this,
|
|
145
291
|
C: (f, a) => f(...a)
|
|
146
292
|
}));
|
|
@@ -155,25 +301,29 @@ var EdgeWsConnection = class extends Resource {
|
|
|
155
301
|
this._connectionInfo.protocolHeader
|
|
156
302
|
] : [
|
|
157
303
|
...baseProtocols
|
|
158
|
-
]
|
|
304
|
+
], this._connectionInfo.headers ? {
|
|
305
|
+
headers: this._connectionInfo.headers
|
|
306
|
+
} : void 0);
|
|
159
307
|
const muxer = new WebSocketMuxer(this._ws);
|
|
160
308
|
this._wsMuxer = muxer;
|
|
161
309
|
this._ws.onopen = () => {
|
|
162
310
|
if (this.isOpen) {
|
|
163
311
|
log("connected", void 0, {
|
|
164
|
-
F:
|
|
165
|
-
L:
|
|
312
|
+
F: __dxlog_file3,
|
|
313
|
+
L: 131,
|
|
166
314
|
S: this,
|
|
167
315
|
C: (f, a) => f(...a)
|
|
168
316
|
});
|
|
317
|
+
this._openTimestamp = Date.now();
|
|
169
318
|
this._callbacks.onConnected();
|
|
170
319
|
this._scheduleHeartbeats();
|
|
320
|
+
this._scheduleRateCalculation();
|
|
171
321
|
} else {
|
|
172
322
|
log.verbose("connected after becoming inactive", {
|
|
173
323
|
currentIdentity: this._identity
|
|
174
324
|
}, {
|
|
175
|
-
F:
|
|
176
|
-
L:
|
|
325
|
+
F: __dxlog_file3,
|
|
326
|
+
L: 137,
|
|
177
327
|
S: this,
|
|
178
328
|
C: (f, a) => f(...a)
|
|
179
329
|
});
|
|
@@ -181,12 +331,12 @@ var EdgeWsConnection = class extends Resource {
|
|
|
181
331
|
};
|
|
182
332
|
this._ws.onclose = (event) => {
|
|
183
333
|
if (this.isOpen) {
|
|
184
|
-
log.warn("disconnected
|
|
334
|
+
log.warn("server disconnected", {
|
|
185
335
|
code: event.code,
|
|
186
336
|
reason: event.reason
|
|
187
337
|
}, {
|
|
188
|
-
F:
|
|
189
|
-
L:
|
|
338
|
+
F: __dxlog_file3,
|
|
339
|
+
L: 142,
|
|
190
340
|
S: this,
|
|
191
341
|
C: (f, a) => f(...a)
|
|
192
342
|
});
|
|
@@ -200,8 +350,8 @@ var EdgeWsConnection = class extends Resource {
|
|
|
200
350
|
error: event.error,
|
|
201
351
|
info: event.message
|
|
202
352
|
}, {
|
|
203
|
-
F:
|
|
204
|
-
L:
|
|
353
|
+
F: __dxlog_file3,
|
|
354
|
+
L: 149,
|
|
205
355
|
S: this,
|
|
206
356
|
C: (f, a) => f(...a)
|
|
207
357
|
});
|
|
@@ -210,8 +360,8 @@ var EdgeWsConnection = class extends Resource {
|
|
|
210
360
|
log.verbose("error ignored on closed connection", {
|
|
211
361
|
error: event.error
|
|
212
362
|
}, {
|
|
213
|
-
F:
|
|
214
|
-
L:
|
|
363
|
+
F: __dxlog_file3,
|
|
364
|
+
L: 152,
|
|
215
365
|
S: this,
|
|
216
366
|
C: (f, a) => f(...a)
|
|
217
367
|
});
|
|
@@ -222,8 +372,8 @@ var EdgeWsConnection = class extends Resource {
|
|
|
222
372
|
log.verbose("message ignored on closed connection", {
|
|
223
373
|
event: event.type
|
|
224
374
|
}, {
|
|
225
|
-
F:
|
|
226
|
-
L:
|
|
375
|
+
F: __dxlog_file3,
|
|
376
|
+
L: 160,
|
|
227
377
|
S: this,
|
|
228
378
|
C: (f, a) => f(...a)
|
|
229
379
|
});
|
|
@@ -231,21 +381,27 @@ var EdgeWsConnection = class extends Resource {
|
|
|
231
381
|
}
|
|
232
382
|
this._lastReceivedMessageTimestamp = Date.now();
|
|
233
383
|
if (event.data === "__pong__") {
|
|
384
|
+
if (this._pingTimestamp) {
|
|
385
|
+
this._rtt = Date.now() - this._pingTimestamp;
|
|
386
|
+
this._pingTimestamp = void 0;
|
|
387
|
+
}
|
|
234
388
|
this._rescheduleHeartbeatTimeout();
|
|
235
389
|
return;
|
|
236
390
|
}
|
|
237
391
|
const bytes = await toUint8Array(event.data);
|
|
392
|
+
this._recordBytes(0, bytes.byteLength);
|
|
238
393
|
if (!this.isOpen) {
|
|
239
394
|
return;
|
|
240
395
|
}
|
|
396
|
+
this._messagesReceived++;
|
|
241
397
|
const message = this._ws?.protocol?.includes(EdgeWebsocketProtocol.V0) ? buf.fromBinary(MessageSchema, bytes) : muxer.receiveData(bytes);
|
|
242
398
|
if (message) {
|
|
243
399
|
log("received", {
|
|
244
400
|
from: message.source,
|
|
245
401
|
payload: protocol.getPayloadType(message)
|
|
246
402
|
}, {
|
|
247
|
-
F:
|
|
248
|
-
L:
|
|
403
|
+
F: __dxlog_file3,
|
|
404
|
+
L: 186,
|
|
249
405
|
S: this,
|
|
250
406
|
C: (f, a) => f(...a)
|
|
251
407
|
});
|
|
@@ -265,20 +421,20 @@ var EdgeWsConnection = class extends Resource {
|
|
|
265
421
|
if (err instanceof Error && err.message.includes("WebSocket is closed before the connection is established.")) {
|
|
266
422
|
return;
|
|
267
423
|
}
|
|
268
|
-
log.warn("
|
|
424
|
+
log.warn("error closing websocket", {
|
|
269
425
|
err
|
|
270
426
|
}, {
|
|
271
|
-
F:
|
|
272
|
-
L:
|
|
427
|
+
F: __dxlog_file3,
|
|
428
|
+
L: 204,
|
|
273
429
|
S: this,
|
|
274
430
|
C: (f, a) => f(...a)
|
|
275
431
|
});
|
|
276
432
|
}
|
|
277
433
|
}
|
|
278
434
|
_scheduleHeartbeats() {
|
|
279
|
-
|
|
280
|
-
F:
|
|
281
|
-
L:
|
|
435
|
+
invariant3(this._ws, void 0, {
|
|
436
|
+
F: __dxlog_file3,
|
|
437
|
+
L: 209,
|
|
282
438
|
S: this,
|
|
283
439
|
A: [
|
|
284
440
|
"this._ws",
|
|
@@ -286,8 +442,10 @@ var EdgeWsConnection = class extends Resource {
|
|
|
286
442
|
]
|
|
287
443
|
});
|
|
288
444
|
scheduleTaskInterval(this._ctx, async () => {
|
|
445
|
+
this._pingTimestamp = Date.now();
|
|
289
446
|
this._ws?.send("__ping__");
|
|
290
447
|
}, SIGNAL_KEEPALIVE_INTERVAL);
|
|
448
|
+
this._pingTimestamp = Date.now();
|
|
291
449
|
this._ws.send("__ping__");
|
|
292
450
|
this._rescheduleHeartbeatTimeout();
|
|
293
451
|
}
|
|
@@ -297,8 +455,8 @@ var EdgeWsConnection = class extends Resource {
|
|
|
297
455
|
}
|
|
298
456
|
void this._inactivityTimeoutCtx?.dispose();
|
|
299
457
|
this._inactivityTimeoutCtx = new Context(void 0, {
|
|
300
|
-
F:
|
|
301
|
-
L:
|
|
458
|
+
F: __dxlog_file3,
|
|
459
|
+
L: 230
|
|
302
460
|
});
|
|
303
461
|
scheduleTask(this._inactivityTimeoutCtx, () => {
|
|
304
462
|
if (this.isOpen) {
|
|
@@ -306,8 +464,8 @@ var EdgeWsConnection = class extends Resource {
|
|
|
306
464
|
log.warn("restart due to inactivity timeout", {
|
|
307
465
|
lastReceivedMessageTimestamp: this._lastReceivedMessageTimestamp
|
|
308
466
|
}, {
|
|
309
|
-
F:
|
|
310
|
-
L:
|
|
467
|
+
F: __dxlog_file3,
|
|
468
|
+
L: 236,
|
|
311
469
|
S: this,
|
|
312
470
|
C: (f, a) => f(...a)
|
|
313
471
|
});
|
|
@@ -318,6 +476,47 @@ var EdgeWsConnection = class extends Resource {
|
|
|
318
476
|
}
|
|
319
477
|
}, SIGNAL_KEEPALIVE_TIMEOUT);
|
|
320
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
|
+
}
|
|
321
520
|
};
|
|
322
521
|
_ts_decorate([
|
|
323
522
|
logInfo
|
|
@@ -350,24 +549,25 @@ function _ts_decorate2(decorators, target, key, desc) {
|
|
|
350
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;
|
|
351
550
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
352
551
|
}
|
|
353
|
-
var
|
|
552
|
+
var __dxlog_file4 = "/__w/dxos/dxos/packages/core/mesh/edge-client/src/edge-client.ts";
|
|
354
553
|
var DEFAULT_TIMEOUT = 1e4;
|
|
554
|
+
var STATUS_REFRESH_INTERVAL = 1e3;
|
|
355
555
|
var EdgeClient = class extends Resource2 {
|
|
356
556
|
_identity;
|
|
357
557
|
_config;
|
|
358
|
-
statusChanged;
|
|
359
|
-
_persistentLifecycle
|
|
360
|
-
|
|
361
|
-
|
|
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();
|
|
362
565
|
_baseWsUrl;
|
|
363
566
|
_baseHttpUrl;
|
|
364
|
-
_currentConnection;
|
|
365
|
-
_ready;
|
|
567
|
+
_currentConnection = void 0;
|
|
568
|
+
_ready = new Trigger();
|
|
366
569
|
constructor(_identity, _config) {
|
|
367
|
-
super(), this._identity = _identity, this._config = _config
|
|
368
|
-
start: async () => this._connect(),
|
|
369
|
-
stop: async (state) => this._disconnect(state)
|
|
370
|
-
}), this._messageListeners = /* @__PURE__ */ new Set(), this._reconnectListeners = /* @__PURE__ */ new Set(), this._currentConnection = void 0, this._ready = new Trigger(), this._isActive = (connection) => connection === this._currentConnection;
|
|
570
|
+
super(), this._identity = _identity, this._config = _config;
|
|
371
571
|
this._baseWsUrl = getEdgeUrlWithProtocol(_config.socketEndpoint, "ws");
|
|
372
572
|
this._baseHttpUrl = getEdgeUrlWithProtocol(_config.socketEndpoint, "http");
|
|
373
573
|
}
|
|
@@ -380,7 +580,15 @@ var EdgeClient = class extends Resource2 {
|
|
|
380
580
|
};
|
|
381
581
|
}
|
|
382
582
|
get status() {
|
|
383
|
-
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
|
+
};
|
|
384
592
|
}
|
|
385
593
|
get identityKey() {
|
|
386
594
|
return this._identity.identityKey;
|
|
@@ -394,8 +602,8 @@ var EdgeClient = class extends Resource2 {
|
|
|
394
602
|
identity,
|
|
395
603
|
oldIdentity: this._identity
|
|
396
604
|
}, {
|
|
397
|
-
F:
|
|
398
|
-
L:
|
|
605
|
+
F: __dxlog_file4,
|
|
606
|
+
L: 121,
|
|
399
607
|
S: this,
|
|
400
608
|
C: (f, a) => f(...a)
|
|
401
609
|
});
|
|
@@ -404,6 +612,38 @@ var EdgeClient = class extends Resource2 {
|
|
|
404
612
|
void this._persistentLifecycle.scheduleRestart();
|
|
405
613
|
}
|
|
406
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
|
+
}
|
|
407
647
|
onMessage(listener) {
|
|
408
648
|
this._messageListeners.add(listener);
|
|
409
649
|
return () => this._messageListeners.delete(listener);
|
|
@@ -417,8 +657,8 @@ var EdgeClient = class extends Resource2 {
|
|
|
417
657
|
listener();
|
|
418
658
|
} catch (error) {
|
|
419
659
|
log2.catch(error, void 0, {
|
|
420
|
-
F:
|
|
421
|
-
L:
|
|
660
|
+
F: __dxlog_file4,
|
|
661
|
+
L: 176,
|
|
422
662
|
S: this,
|
|
423
663
|
C: (f, a) => f(...a)
|
|
424
664
|
});
|
|
@@ -435,8 +675,8 @@ var EdgeClient = class extends Resource2 {
|
|
|
435
675
|
log2("opening...", {
|
|
436
676
|
info: this.info
|
|
437
677
|
}, {
|
|
438
|
-
F:
|
|
439
|
-
L:
|
|
678
|
+
F: __dxlog_file4,
|
|
679
|
+
L: 189,
|
|
440
680
|
S: this,
|
|
441
681
|
C: (f, a) => f(...a)
|
|
442
682
|
});
|
|
@@ -444,12 +684,18 @@ var EdgeClient = class extends Resource2 {
|
|
|
444
684
|
log2.warn("Error while opening connection", {
|
|
445
685
|
err
|
|
446
686
|
}, {
|
|
447
|
-
F:
|
|
448
|
-
L:
|
|
687
|
+
F: __dxlog_file4,
|
|
688
|
+
L: 191,
|
|
449
689
|
S: this,
|
|
450
690
|
C: (f, a) => f(...a)
|
|
451
691
|
});
|
|
452
692
|
});
|
|
693
|
+
scheduleTaskInterval2(this._ctx, async () => {
|
|
694
|
+
if (!this._currentConnection) {
|
|
695
|
+
return;
|
|
696
|
+
}
|
|
697
|
+
this.statusChanged.emit(this.status);
|
|
698
|
+
}, STATUS_REFRESH_INTERVAL);
|
|
453
699
|
}
|
|
454
700
|
/**
|
|
455
701
|
* Close connection and free resources.
|
|
@@ -458,8 +704,8 @@ var EdgeClient = class extends Resource2 {
|
|
|
458
704
|
log2("closing...", {
|
|
459
705
|
peerKey: this._identity.peerKey
|
|
460
706
|
}, {
|
|
461
|
-
F:
|
|
462
|
-
L:
|
|
707
|
+
F: __dxlog_file4,
|
|
708
|
+
L: 211,
|
|
463
709
|
S: this,
|
|
464
710
|
C: (f, a) => f(...a)
|
|
465
711
|
});
|
|
@@ -475,8 +721,8 @@ var EdgeClient = class extends Resource2 {
|
|
|
475
721
|
const protocolHeader = this._config.disableAuth ? void 0 : await this._createAuthHeader(path);
|
|
476
722
|
if (this._identity !== identity) {
|
|
477
723
|
log2("identity changed during auth header request", void 0, {
|
|
478
|
-
F:
|
|
479
|
-
L:
|
|
724
|
+
F: __dxlog_file4,
|
|
725
|
+
L: 225,
|
|
480
726
|
S: this,
|
|
481
727
|
C: (f, a) => f(...a)
|
|
482
728
|
});
|
|
@@ -488,14 +734,17 @@ var EdgeClient = class extends Resource2 {
|
|
|
488
734
|
url: url.toString(),
|
|
489
735
|
protocolHeader
|
|
490
736
|
}, {
|
|
491
|
-
F:
|
|
492
|
-
L:
|
|
737
|
+
F: __dxlog_file4,
|
|
738
|
+
L: 231,
|
|
493
739
|
S: this,
|
|
494
740
|
C: (f, a) => f(...a)
|
|
495
741
|
});
|
|
496
742
|
const connection = new EdgeWsConnection(identity, {
|
|
497
743
|
url,
|
|
498
|
-
protocolHeader
|
|
744
|
+
protocolHeader,
|
|
745
|
+
headers: this._config.clientTag ? {
|
|
746
|
+
"X-DXOS-Client-Tag": this._config.clientTag
|
|
747
|
+
} : void 0
|
|
499
748
|
}, {
|
|
500
749
|
onConnected: () => {
|
|
501
750
|
if (this._isActive(connection)) {
|
|
@@ -503,8 +752,8 @@ var EdgeClient = class extends Resource2 {
|
|
|
503
752
|
this._notifyReconnected();
|
|
504
753
|
} else {
|
|
505
754
|
log2.verbose("connected callback ignored, because connection is not active", void 0, {
|
|
506
|
-
F:
|
|
507
|
-
L:
|
|
755
|
+
F: __dxlog_file4,
|
|
756
|
+
L: 245,
|
|
508
757
|
S: this,
|
|
509
758
|
C: (f, a) => f(...a)
|
|
510
759
|
});
|
|
@@ -516,8 +765,8 @@ var EdgeClient = class extends Resource2 {
|
|
|
516
765
|
void this._persistentLifecycle.scheduleRestart();
|
|
517
766
|
} else {
|
|
518
767
|
log2.verbose("restart requested by inactive connection", void 0, {
|
|
519
|
-
F:
|
|
520
|
-
L:
|
|
768
|
+
F: __dxlog_file4,
|
|
769
|
+
L: 253,
|
|
521
770
|
S: this,
|
|
522
771
|
C: (f, a) => f(...a)
|
|
523
772
|
});
|
|
@@ -532,8 +781,8 @@ var EdgeClient = class extends Resource2 {
|
|
|
532
781
|
from: message.source,
|
|
533
782
|
type: message.payload?.typeUrl
|
|
534
783
|
}, {
|
|
535
|
-
F:
|
|
536
|
-
L:
|
|
784
|
+
F: __dxlog_file4,
|
|
785
|
+
L: 261,
|
|
537
786
|
S: this,
|
|
538
787
|
C: (f, a) => f(...a)
|
|
539
788
|
});
|
|
@@ -569,8 +818,8 @@ var EdgeClient = class extends Resource2 {
|
|
|
569
818
|
log2.error("ws reconnect listener failed", {
|
|
570
819
|
err
|
|
571
820
|
}, {
|
|
572
|
-
F:
|
|
573
|
-
L:
|
|
821
|
+
F: __dxlog_file4,
|
|
822
|
+
L: 296,
|
|
574
823
|
S: this,
|
|
575
824
|
C: (f, a) => f(...a)
|
|
576
825
|
});
|
|
@@ -586,38 +835,14 @@ var EdgeClient = class extends Resource2 {
|
|
|
586
835
|
err,
|
|
587
836
|
payload: protocol.getPayloadType(message)
|
|
588
837
|
}, {
|
|
589
|
-
F:
|
|
590
|
-
L:
|
|
838
|
+
F: __dxlog_file4,
|
|
839
|
+
L: 306,
|
|
591
840
|
S: this,
|
|
592
841
|
C: (f, a) => f(...a)
|
|
593
842
|
});
|
|
594
843
|
}
|
|
595
844
|
}
|
|
596
845
|
}
|
|
597
|
-
/**
|
|
598
|
-
* Send message.
|
|
599
|
-
* NOTE: The message is guaranteed to be delivered but the service must respond with a message to confirm processing.
|
|
600
|
-
*/
|
|
601
|
-
async send(message) {
|
|
602
|
-
if (this._ready.state !== TriggerState.RESOLVED) {
|
|
603
|
-
log2("waiting for websocket to become ready", void 0, {
|
|
604
|
-
F: __dxlog_file3,
|
|
605
|
-
L: 246,
|
|
606
|
-
S: this,
|
|
607
|
-
C: (f, a) => f(...a)
|
|
608
|
-
});
|
|
609
|
-
await this._ready.wait({
|
|
610
|
-
timeout: this._config.timeout ?? DEFAULT_TIMEOUT
|
|
611
|
-
});
|
|
612
|
-
}
|
|
613
|
-
if (!this._currentConnection) {
|
|
614
|
-
throw new EdgeConnectionClosedError();
|
|
615
|
-
}
|
|
616
|
-
if (message.source && (message.source.peerKey !== this._identity.peerKey || message.source.identityKey !== this.identityKey)) {
|
|
617
|
-
throw new EdgeIdentityChangedError();
|
|
618
|
-
}
|
|
619
|
-
this._currentConnection.send(message);
|
|
620
|
-
}
|
|
621
846
|
async _createAuthHeader(path) {
|
|
622
847
|
const httpUrl = new URL(path, this._baseHttpUrl);
|
|
623
848
|
httpUrl.protocol = getEdgeUrlWithProtocol(this._baseWsUrl.toString(), "http");
|
|
@@ -631,15 +856,15 @@ var EdgeClient = class extends Resource2 {
|
|
|
631
856
|
status: response.status,
|
|
632
857
|
statusText: response.statusText
|
|
633
858
|
}, {
|
|
634
|
-
F:
|
|
635
|
-
L:
|
|
859
|
+
F: __dxlog_file4,
|
|
860
|
+
L: 318,
|
|
636
861
|
S: this,
|
|
637
862
|
C: (f, a) => f(...a)
|
|
638
863
|
});
|
|
639
864
|
return void 0;
|
|
640
865
|
}
|
|
641
866
|
}
|
|
642
|
-
_isActive;
|
|
867
|
+
_isActive = (connection) => connection === this._currentConnection;
|
|
643
868
|
};
|
|
644
869
|
_ts_decorate2([
|
|
645
870
|
logInfo2
|
|
@@ -649,128 +874,25 @@ var encodePresentationWsAuthHeader = (encodedPresentation) => {
|
|
|
649
874
|
return `base64url.bearer.authorization.dxos.org.${encodedToken}`;
|
|
650
875
|
};
|
|
651
876
|
|
|
652
|
-
// src/auth.ts
|
|
653
|
-
import { createCredential, signPresentation } from "@dxos/credentials";
|
|
654
|
-
import { invariant as invariant3 } from "@dxos/invariant";
|
|
655
|
-
import { Keyring } from "@dxos/keyring";
|
|
656
|
-
import { PublicKey } from "@dxos/keys";
|
|
657
|
-
var __dxlog_file4 = "/__w/dxos/dxos/packages/core/mesh/edge-client/src/auth.ts";
|
|
658
|
-
var createDeviceEdgeIdentity = async (signer, key) => {
|
|
659
|
-
return {
|
|
660
|
-
identityKey: key.toHex(),
|
|
661
|
-
peerKey: key.toHex(),
|
|
662
|
-
presentCredentials: async ({ challenge }) => {
|
|
663
|
-
return signPresentation({
|
|
664
|
-
presentation: {
|
|
665
|
-
credentials: [
|
|
666
|
-
// Verifier requires at least one credential in the presentation to establish the subject.
|
|
667
|
-
await createCredential({
|
|
668
|
-
assertion: {
|
|
669
|
-
"@type": "dxos.halo.credentials.Auth"
|
|
670
|
-
},
|
|
671
|
-
issuer: key,
|
|
672
|
-
subject: key,
|
|
673
|
-
signer
|
|
674
|
-
})
|
|
675
|
-
]
|
|
676
|
-
},
|
|
677
|
-
signer,
|
|
678
|
-
signerKey: key,
|
|
679
|
-
nonce: challenge
|
|
680
|
-
});
|
|
681
|
-
}
|
|
682
|
-
};
|
|
683
|
-
};
|
|
684
|
-
var createChainEdgeIdentity = async (signer, identityKey, peerKey, chain, credentials) => {
|
|
685
|
-
const credentialsToSign = credentials.length > 0 ? credentials : [
|
|
686
|
-
await createCredential({
|
|
687
|
-
assertion: {
|
|
688
|
-
"@type": "dxos.halo.credentials.Auth"
|
|
689
|
-
},
|
|
690
|
-
issuer: identityKey,
|
|
691
|
-
subject: identityKey,
|
|
692
|
-
signer,
|
|
693
|
-
chain,
|
|
694
|
-
signingKey: peerKey
|
|
695
|
-
})
|
|
696
|
-
];
|
|
697
|
-
return {
|
|
698
|
-
identityKey: identityKey.toHex(),
|
|
699
|
-
peerKey: peerKey.toHex(),
|
|
700
|
-
presentCredentials: async ({ challenge }) => {
|
|
701
|
-
invariant3(chain, void 0, {
|
|
702
|
-
F: __dxlog_file4,
|
|
703
|
-
L: 75,
|
|
704
|
-
S: void 0,
|
|
705
|
-
A: [
|
|
706
|
-
"chain",
|
|
707
|
-
""
|
|
708
|
-
]
|
|
709
|
-
});
|
|
710
|
-
return signPresentation({
|
|
711
|
-
presentation: {
|
|
712
|
-
credentials: credentialsToSign
|
|
713
|
-
},
|
|
714
|
-
signer,
|
|
715
|
-
nonce: challenge,
|
|
716
|
-
signerKey: peerKey,
|
|
717
|
-
chain
|
|
718
|
-
});
|
|
719
|
-
}
|
|
720
|
-
};
|
|
721
|
-
};
|
|
722
|
-
var createEphemeralEdgeIdentity = async () => {
|
|
723
|
-
const keyring = new Keyring();
|
|
724
|
-
const key = await keyring.createKey();
|
|
725
|
-
return createDeviceEdgeIdentity(keyring, key);
|
|
726
|
-
};
|
|
727
|
-
var createTestHaloEdgeIdentity = async (signer, identityKey, deviceKey) => {
|
|
728
|
-
const deviceAdmission = await createCredential({
|
|
729
|
-
assertion: {
|
|
730
|
-
"@type": "dxos.halo.credentials.AuthorizedDevice",
|
|
731
|
-
deviceKey,
|
|
732
|
-
identityKey
|
|
733
|
-
},
|
|
734
|
-
issuer: identityKey,
|
|
735
|
-
subject: deviceKey,
|
|
736
|
-
signer
|
|
737
|
-
});
|
|
738
|
-
return createChainEdgeIdentity(signer, identityKey, deviceKey, {
|
|
739
|
-
credential: deviceAdmission
|
|
740
|
-
}, [
|
|
741
|
-
await createCredential({
|
|
742
|
-
assertion: {
|
|
743
|
-
"@type": "dxos.halo.credentials.Auth"
|
|
744
|
-
},
|
|
745
|
-
issuer: identityKey,
|
|
746
|
-
subject: identityKey,
|
|
747
|
-
signer
|
|
748
|
-
})
|
|
749
|
-
]);
|
|
750
|
-
};
|
|
751
|
-
var createStubEdgeIdentity = () => {
|
|
752
|
-
const identityKey = PublicKey.random();
|
|
753
|
-
const deviceKey = PublicKey.random();
|
|
754
|
-
return {
|
|
755
|
-
identityKey: identityKey.toHex(),
|
|
756
|
-
peerKey: deviceKey.toHex(),
|
|
757
|
-
presentCredentials: async () => {
|
|
758
|
-
throw new Error("Stub identity does not support authentication.");
|
|
759
|
-
}
|
|
760
|
-
};
|
|
761
|
-
};
|
|
762
|
-
|
|
763
877
|
// src/edge-http-client.ts
|
|
764
|
-
import
|
|
765
|
-
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";
|
|
766
882
|
import { sleep } from "@dxos/async";
|
|
767
|
-
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";
|
|
768
886
|
import { log as log4 } from "@dxos/log";
|
|
769
|
-
import { EdgeAuthChallengeError, EdgeCallFailedError } from "@dxos/protocols";
|
|
887
|
+
import { EDGE_CLIENT_TAG_HEADER, EdgeAuthChallengeError, EdgeCallFailedError } from "@dxos/protocols";
|
|
770
888
|
import { createUrl } from "@dxos/util";
|
|
771
889
|
|
|
772
890
|
// src/http-client.ts
|
|
773
|
-
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";
|
|
774
896
|
import { log as log3 } from "@dxos/log";
|
|
775
897
|
var __dxlog_file5 = "/__w/dxos/dxos/packages/core/mesh/edge-client/src/http-client.ts";
|
|
776
898
|
var HttpConfig = class _HttpConfig extends Context2.Tag("HttpConfig")() {
|
|
@@ -780,11 +902,11 @@ var HttpConfig = class _HttpConfig extends Context2.Tag("HttpConfig")() {
|
|
|
780
902
|
retryBaseDelay: Duration.millis(1e3)
|
|
781
903
|
});
|
|
782
904
|
};
|
|
783
|
-
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 } = {}) => {
|
|
784
906
|
return effect.pipe(Effect.flatMap((res) => (
|
|
785
907
|
// Treat 500 errors as retryable?
|
|
786
908
|
res.status === 500 ? Effect.fail(new Error(res.status.toString())) : res.json
|
|
787
|
-
)), Effect.timeout(
|
|
909
|
+
)), Effect.timeout(timeout2), Effect.retry({
|
|
788
910
|
schedule: Schedule.exponential(retryBaseDelay).pipe(Schedule.jittered),
|
|
789
911
|
times: retryTimes
|
|
790
912
|
}));
|
|
@@ -793,14 +915,16 @@ var withRetryConfig = (effect) => Effect.gen(function* () {
|
|
|
793
915
|
const config = yield* HttpConfig;
|
|
794
916
|
return yield* withRetry(effect, config);
|
|
795
917
|
});
|
|
796
|
-
var withLogging = (effect) => effect.pipe(Effect.tap((res) =>
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
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
|
+
}));
|
|
804
928
|
var encodeAuthHeader = (challenge) => {
|
|
805
929
|
const encodedChallenge = Buffer.from(challenge).toString("base64");
|
|
806
930
|
return `VerifiablePresentation pb;base64,${encodedChallenge}`;
|
|
@@ -811,20 +935,23 @@ var __dxlog_file6 = "/__w/dxos/dxos/packages/core/mesh/edge-client/src/edge-http
|
|
|
811
935
|
var DEFAULT_RETRY_TIMEOUT = 1500;
|
|
812
936
|
var DEFAULT_RETRY_JITTER = 500;
|
|
813
937
|
var DEFAULT_MAX_RETRIES_COUNT = 3;
|
|
938
|
+
var WARNING_BODY_SIZE = 10 * 1024 * 1024;
|
|
814
939
|
var EdgeHttpClient = class {
|
|
815
940
|
_baseUrl;
|
|
941
|
+
_clientTag;
|
|
816
942
|
_edgeIdentity;
|
|
817
943
|
/**
|
|
818
944
|
* Auth header is cached until receiving the next 401 from EDGE, at which point it gets refreshed.
|
|
819
945
|
*/
|
|
820
946
|
_authHeader;
|
|
821
|
-
constructor(baseUrl) {
|
|
947
|
+
constructor(baseUrl, options) {
|
|
822
948
|
this._baseUrl = getEdgeUrlWithProtocol(baseUrl, "http");
|
|
949
|
+
this._clientTag = options?.clientTag;
|
|
823
950
|
log4("created", {
|
|
824
951
|
url: this._baseUrl
|
|
825
952
|
}, {
|
|
826
953
|
F: __dxlog_file6,
|
|
827
|
-
L:
|
|
954
|
+
L: 120,
|
|
828
955
|
S: this,
|
|
829
956
|
C: (f, a) => f(...a)
|
|
830
957
|
});
|
|
@@ -841,24 +968,25 @@ var EdgeHttpClient = class {
|
|
|
841
968
|
//
|
|
842
969
|
// Status
|
|
843
970
|
//
|
|
844
|
-
async getStatus(args) {
|
|
845
|
-
return this._call(new URL("/status", this.baseUrl), {
|
|
971
|
+
async getStatus(ctx, args) {
|
|
972
|
+
return this._call(ctx, new URL("/status", this.baseUrl), {
|
|
846
973
|
...args,
|
|
847
|
-
method: "GET"
|
|
974
|
+
method: "GET",
|
|
975
|
+
auth: true
|
|
848
976
|
});
|
|
849
977
|
}
|
|
850
978
|
//
|
|
851
979
|
// Agents
|
|
852
980
|
//
|
|
853
|
-
createAgent(body, args) {
|
|
854
|
-
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), {
|
|
855
983
|
...args,
|
|
856
984
|
method: "POST",
|
|
857
985
|
body
|
|
858
986
|
});
|
|
859
987
|
}
|
|
860
|
-
getAgentStatus(request, args) {
|
|
861
|
-
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), {
|
|
862
990
|
...args,
|
|
863
991
|
method: "GET"
|
|
864
992
|
});
|
|
@@ -866,14 +994,14 @@ var EdgeHttpClient = class {
|
|
|
866
994
|
//
|
|
867
995
|
// Credentials
|
|
868
996
|
//
|
|
869
|
-
getCredentialsForNotarization(spaceId, args) {
|
|
870
|
-
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), {
|
|
871
999
|
...args,
|
|
872
1000
|
method: "GET"
|
|
873
1001
|
});
|
|
874
1002
|
}
|
|
875
|
-
async notarizeCredentials(spaceId, body, args) {
|
|
876
|
-
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), {
|
|
877
1005
|
...args,
|
|
878
1006
|
body,
|
|
879
1007
|
method: "POST"
|
|
@@ -882,8 +1010,8 @@ var EdgeHttpClient = class {
|
|
|
882
1010
|
//
|
|
883
1011
|
// Identity
|
|
884
1012
|
//
|
|
885
|
-
async recoverIdentity(body, args) {
|
|
886
|
-
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), {
|
|
887
1015
|
...args,
|
|
888
1016
|
body,
|
|
889
1017
|
method: "POST"
|
|
@@ -892,8 +1020,8 @@ var EdgeHttpClient = class {
|
|
|
892
1020
|
//
|
|
893
1021
|
// Invitations
|
|
894
1022
|
//
|
|
895
|
-
async joinSpaceByInvitation(spaceId, body, args) {
|
|
896
|
-
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), {
|
|
897
1025
|
...args,
|
|
898
1026
|
body,
|
|
899
1027
|
method: "POST"
|
|
@@ -902,14 +1030,8 @@ var EdgeHttpClient = class {
|
|
|
902
1030
|
//
|
|
903
1031
|
// OAuth and credentials
|
|
904
1032
|
//
|
|
905
|
-
async
|
|
906
|
-
return this._call(new URL("/
|
|
907
|
-
...args,
|
|
908
|
-
method: "GET"
|
|
909
|
-
});
|
|
910
|
-
}
|
|
911
|
-
async initiateOAuthFlow(body, args) {
|
|
912
|
-
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), {
|
|
913
1035
|
...args,
|
|
914
1036
|
body,
|
|
915
1037
|
method: "POST"
|
|
@@ -918,8 +1040,8 @@ var EdgeHttpClient = class {
|
|
|
918
1040
|
//
|
|
919
1041
|
// Spaces
|
|
920
1042
|
//
|
|
921
|
-
async createSpace(body, args) {
|
|
922
|
-
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), {
|
|
923
1045
|
...args,
|
|
924
1046
|
body,
|
|
925
1047
|
method: "POST"
|
|
@@ -928,9 +1050,18 @@ var EdgeHttpClient = class {
|
|
|
928
1050
|
//
|
|
929
1051
|
// Queues
|
|
930
1052
|
//
|
|
931
|
-
async queryQueue(subspaceTag, spaceId, query, args) {
|
|
932
|
-
const
|
|
933
|
-
|
|
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), {
|
|
934
1065
|
after: query.after,
|
|
935
1066
|
before: query.before,
|
|
936
1067
|
limit: query.limit,
|
|
@@ -941,8 +1072,8 @@ var EdgeHttpClient = class {
|
|
|
941
1072
|
method: "GET"
|
|
942
1073
|
});
|
|
943
1074
|
}
|
|
944
|
-
async insertIntoQueue(subspaceTag, spaceId, queueId, objects, args) {
|
|
945
|
-
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), {
|
|
946
1077
|
...args,
|
|
947
1078
|
body: {
|
|
948
1079
|
objects
|
|
@@ -950,8 +1081,8 @@ var EdgeHttpClient = class {
|
|
|
950
1081
|
method: "POST"
|
|
951
1082
|
});
|
|
952
1083
|
}
|
|
953
|
-
async deleteFromQueue(subspaceTag, spaceId, queueId, objectIds, args) {
|
|
954
|
-
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), {
|
|
955
1086
|
ids: objectIds.join(",")
|
|
956
1087
|
}), {
|
|
957
1088
|
...args,
|
|
@@ -961,95 +1092,225 @@ var EdgeHttpClient = class {
|
|
|
961
1092
|
//
|
|
962
1093
|
// Functions
|
|
963
1094
|
//
|
|
964
|
-
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
|
+
}
|
|
965
1109
|
const path = [
|
|
966
1110
|
"functions",
|
|
967
1111
|
...pathParts.functionId ? [
|
|
968
1112
|
pathParts.functionId
|
|
969
1113
|
] : []
|
|
970
1114
|
].join("/");
|
|
971
|
-
return this._call(new URL(path, this.baseUrl), {
|
|
1115
|
+
return this._call(ctx, new URL(path, this.baseUrl), {
|
|
972
1116
|
...args,
|
|
973
|
-
body,
|
|
974
|
-
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"
|
|
975
1146
|
});
|
|
976
1147
|
}
|
|
977
1148
|
//
|
|
978
1149
|
// Workflows
|
|
979
1150
|
//
|
|
980
|
-
async executeWorkflow(spaceId, graphId, input, args) {
|
|
981
|
-
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), {
|
|
982
1153
|
...args,
|
|
983
1154
|
body: input,
|
|
984
1155
|
method: "POST"
|
|
985
1156
|
});
|
|
986
1157
|
}
|
|
987
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
|
+
//
|
|
988
1215
|
// Internal
|
|
989
1216
|
//
|
|
990
|
-
async _fetch(url,
|
|
991
|
-
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);
|
|
992
1219
|
}
|
|
993
1220
|
// TODO(burdon): Refactor with effect (see edge-http-client.test.ts).
|
|
994
|
-
async _call(url, args) {
|
|
1221
|
+
async _call(ctx, url, args) {
|
|
995
1222
|
const shouldRetry = createRetryHandler(args);
|
|
996
|
-
const requestContext = args.context ?? new Context3(void 0, {
|
|
997
|
-
F: __dxlog_file6,
|
|
998
|
-
L: 293
|
|
999
|
-
});
|
|
1000
1223
|
log4("fetch", {
|
|
1001
1224
|
url,
|
|
1002
1225
|
request: args.body
|
|
1003
1226
|
}, {
|
|
1004
1227
|
F: __dxlog_file6,
|
|
1005
|
-
L:
|
|
1228
|
+
L: 472,
|
|
1006
1229
|
S: this,
|
|
1007
1230
|
C: (f, a) => f(...a)
|
|
1008
1231
|
});
|
|
1232
|
+
const traceHeaders = getTraceHeaders(ctx);
|
|
1009
1233
|
let handledAuth = false;
|
|
1234
|
+
const tryCount = 1;
|
|
1010
1235
|
while (true) {
|
|
1011
|
-
let processingError;
|
|
1012
|
-
let retryAfterHeaderValue = Number.NaN;
|
|
1236
|
+
let processingError = void 0;
|
|
1013
1237
|
try {
|
|
1014
|
-
|
|
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
|
+
});
|
|
1015
1255
|
const response = await fetch(url, request);
|
|
1016
|
-
retryAfterHeaderValue = Number(response.headers.get("Retry-After"));
|
|
1017
1256
|
if (response.ok) {
|
|
1018
|
-
const
|
|
1019
|
-
|
|
1020
|
-
return body.data;
|
|
1021
|
-
}
|
|
1022
|
-
log4.warn("unsuccessful edge response", {
|
|
1023
|
-
url,
|
|
1024
|
-
body
|
|
1025
|
-
}, {
|
|
1257
|
+
const body2 = await response.clone().json();
|
|
1258
|
+
invariant4(body2, "Expected body to be present", {
|
|
1026
1259
|
F: __dxlog_file6,
|
|
1027
|
-
L:
|
|
1260
|
+
L: 494,
|
|
1028
1261
|
S: this,
|
|
1029
|
-
|
|
1262
|
+
A: [
|
|
1263
|
+
"body",
|
|
1264
|
+
"'Expected body to be present'"
|
|
1265
|
+
]
|
|
1030
1266
|
});
|
|
1031
|
-
if (
|
|
1032
|
-
|
|
1033
|
-
}
|
|
1034
|
-
|
|
1267
|
+
if (!("success" in body2)) {
|
|
1268
|
+
return body2;
|
|
1269
|
+
}
|
|
1270
|
+
if (body2.success) {
|
|
1271
|
+
return body2.data;
|
|
1035
1272
|
}
|
|
1036
1273
|
} else if (response.status === 401 && !handledAuth) {
|
|
1037
1274
|
this._authHeader = await this._handleUnauthorized(response);
|
|
1038
1275
|
handledAuth = true;
|
|
1039
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);
|
|
1040
1292
|
} else {
|
|
1041
|
-
|
|
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);
|
|
1042
1303
|
}
|
|
1043
1304
|
} catch (error) {
|
|
1044
1305
|
processingError = EdgeCallFailedError.fromProcessingFailureCause(error);
|
|
1045
1306
|
}
|
|
1046
|
-
if (processingError
|
|
1047
|
-
log4("retrying edge request", {
|
|
1307
|
+
if (processingError?.isRetryable && await shouldRetry(ctx, processingError.retryAfterMs)) {
|
|
1308
|
+
log4.verbose("retrying edge request", {
|
|
1048
1309
|
url,
|
|
1049
1310
|
processingError
|
|
1050
1311
|
}, {
|
|
1051
1312
|
F: __dxlog_file6,
|
|
1052
|
-
L:
|
|
1313
|
+
L: 525,
|
|
1053
1314
|
S: this,
|
|
1054
1315
|
C: (f, a) => f(...a)
|
|
1055
1316
|
});
|
|
@@ -1062,33 +1323,71 @@ var EdgeHttpClient = class {
|
|
|
1062
1323
|
if (!this._edgeIdentity) {
|
|
1063
1324
|
log4.warn("unauthorized response received before identity was set", void 0, {
|
|
1064
1325
|
F: __dxlog_file6,
|
|
1065
|
-
L:
|
|
1326
|
+
L: 534,
|
|
1066
1327
|
S: this,
|
|
1067
1328
|
C: (f, a) => f(...a)
|
|
1068
1329
|
});
|
|
1069
|
-
throw EdgeCallFailedError.fromHttpFailure(response);
|
|
1330
|
+
throw await EdgeCallFailedError.fromHttpFailure(response);
|
|
1070
1331
|
}
|
|
1071
1332
|
const challenge = await handleAuthChallenge(response, this._edgeIdentity);
|
|
1072
1333
|
return encodeAuthHeader(challenge);
|
|
1073
1334
|
}
|
|
1074
1335
|
};
|
|
1075
|
-
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
|
+
}
|
|
1076
1364
|
return {
|
|
1077
1365
|
method,
|
|
1078
|
-
body:
|
|
1079
|
-
headers
|
|
1080
|
-
|
|
1081
|
-
|
|
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
|
|
1082
1377
|
};
|
|
1378
|
+
if (traceCtx.tracestate) {
|
|
1379
|
+
headers.tracestate = traceCtx.tracestate;
|
|
1380
|
+
}
|
|
1381
|
+
return headers;
|
|
1083
1382
|
};
|
|
1084
|
-
var createRetryHandler = ({ retry }) => {
|
|
1085
|
-
if (!
|
|
1383
|
+
var createRetryHandler = ({ retry: retry2 }) => {
|
|
1384
|
+
if (!retry2 || retry2.count < 1) {
|
|
1086
1385
|
return async () => false;
|
|
1087
1386
|
}
|
|
1088
1387
|
let retries = 0;
|
|
1089
|
-
const maxRetries =
|
|
1090
|
-
const baseTimeout =
|
|
1091
|
-
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;
|
|
1092
1391
|
return async (ctx, retryAfter) => {
|
|
1093
1392
|
if (++retries > maxRetries || ctx.disposed) {
|
|
1094
1393
|
return false;
|
|
@@ -1096,12 +1395,16 @@ var createRetryHandler = ({ retry }) => {
|
|
|
1096
1395
|
if (retryAfter) {
|
|
1097
1396
|
await sleep(retryAfter);
|
|
1098
1397
|
} else {
|
|
1099
|
-
const
|
|
1100
|
-
await sleep(
|
|
1398
|
+
const timeout2 = baseTimeout + Math.random() * jitter;
|
|
1399
|
+
await sleep(timeout2);
|
|
1101
1400
|
}
|
|
1102
1401
|
return true;
|
|
1103
1402
|
};
|
|
1104
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";
|
|
1105
1408
|
export {
|
|
1106
1409
|
CLOUDFLARE_MESSAGE_MAX_BYTES,
|
|
1107
1410
|
CLOUDFLARE_RPC_MAX_BYTES,
|
|
@@ -1109,6 +1412,7 @@ export {
|
|
|
1109
1412
|
EdgeConnectionClosedError,
|
|
1110
1413
|
EdgeHttpClient,
|
|
1111
1414
|
EdgeIdentityChangedError,
|
|
1415
|
+
HttpConfig,
|
|
1112
1416
|
Protocol,
|
|
1113
1417
|
WebSocketMuxer,
|
|
1114
1418
|
createChainEdgeIdentity,
|
|
@@ -1116,9 +1420,13 @@ export {
|
|
|
1116
1420
|
createEphemeralEdgeIdentity,
|
|
1117
1421
|
createStubEdgeIdentity,
|
|
1118
1422
|
createTestHaloEdgeIdentity,
|
|
1423
|
+
encodeAuthHeader,
|
|
1119
1424
|
getTypename,
|
|
1120
1425
|
handleAuthChallenge,
|
|
1121
1426
|
protocol,
|
|
1122
|
-
toUint8Array
|
|
1427
|
+
toUint8Array,
|
|
1428
|
+
withLogging,
|
|
1429
|
+
withRetry,
|
|
1430
|
+
withRetryConfig
|
|
1123
1431
|
};
|
|
1124
1432
|
//# sourceMappingURL=index.mjs.map
|