@dxos/edge-client 0.6.11 → 0.6.12-main.568932b
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-ZWJXA37R.mjs +113 -0
- package/dist/lib/browser/chunk-ZWJXA37R.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +347 -178
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +122 -0
- package/dist/lib/browser/testing/index.mjs.map +7 -0
- package/dist/lib/node/chunk-ANV2HBEH.cjs +136 -0
- package/dist/lib/node/chunk-ANV2HBEH.cjs.map +7 -0
- package/dist/lib/node/index.cjs +346 -175
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/testing/index.cjs +152 -0
- package/dist/lib/node/testing/index.cjs.map +7 -0
- package/dist/lib/node-esm/chunk-HNVT57AU.mjs +115 -0
- package/dist/lib/node-esm/chunk-HNVT57AU.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +647 -0
- package/dist/lib/node-esm/index.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -0
- package/dist/lib/node-esm/testing/index.mjs +123 -0
- package/dist/lib/node-esm/testing/index.mjs.map +7 -0
- package/dist/types/src/auth.d.ts +22 -0
- package/dist/types/src/auth.d.ts.map +1 -0
- package/dist/types/src/defs.d.ts.map +1 -1
- package/dist/types/src/edge-client.d.ts +23 -13
- package/dist/types/src/edge-client.d.ts.map +1 -1
- package/dist/types/src/edge-http-client.d.ts +34 -0
- package/dist/types/src/edge-http-client.d.ts.map +1 -0
- package/dist/types/src/errors.d.ts +4 -1
- package/dist/types/src/errors.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +3 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/protocol.d.ts +2 -2
- package/dist/types/src/protocol.d.ts.map +1 -1
- package/dist/types/src/testing/index.d.ts +2 -0
- package/dist/types/src/testing/index.d.ts.map +1 -0
- package/dist/types/src/testing/test-utils.d.ts +20 -0
- package/dist/types/src/testing/test-utils.d.ts.map +1 -0
- package/dist/types/src/utils.d.ts +2 -0
- package/dist/types/src/utils.d.ts.map +1 -0
- package/package.json +29 -14
- package/src/auth.ts +135 -0
- package/src/defs.ts +2 -3
- package/src/edge-client.test.ts +50 -18
- package/src/edge-client.ts +76 -23
- package/src/edge-http-client.ts +153 -0
- package/src/errors.ts +8 -2
- package/src/index.ts +3 -0
- package/src/persistent-lifecycle.test.ts +2 -2
- package/src/protocol.test.ts +1 -2
- package/src/protocol.ts +2 -2
- package/src/testing/index.ts +5 -0
- package/src/testing/test-utils.ts +111 -0
- package/src/utils.ts +10 -0
- package/src/websocket.test.ts +5 -4
- package/dist/types/src/test-utils.d.ts +0 -11
- package/dist/types/src/test-utils.d.ts.map +0 -1
- package/src/test-utils.ts +0 -49
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Protocol,
|
|
3
|
+
getTypename,
|
|
4
|
+
protocol,
|
|
5
|
+
toUint8Array
|
|
6
|
+
} from "./chunk-ZWJXA37R.mjs";
|
|
7
|
+
|
|
1
8
|
// packages/core/mesh/edge-client/src/index.ts
|
|
2
9
|
export * from "@dxos/protocols/buf/dxos/edge/messenger_pb";
|
|
3
10
|
|
|
@@ -5,123 +12,21 @@ export * from "@dxos/protocols/buf/dxos/edge/messenger_pb";
|
|
|
5
12
|
import WebSocket from "isomorphic-ws";
|
|
6
13
|
import { Trigger, Event, scheduleTaskInterval, scheduleTask, TriggerState } from "@dxos/async";
|
|
7
14
|
import { Context, LifecycleState as LifecycleState2, Resource as Resource2 } from "@dxos/context";
|
|
8
|
-
import {
|
|
15
|
+
import { randomBytes } from "@dxos/crypto";
|
|
9
16
|
import { log as log2 } from "@dxos/log";
|
|
10
|
-
import { buf
|
|
11
|
-
import { MessageSchema as MessageSchema2 } from "@dxos/protocols/buf/dxos/edge/messenger_pb";
|
|
12
|
-
|
|
13
|
-
// packages/core/mesh/edge-client/src/defs.ts
|
|
14
|
-
import { AnySchema } from "@bufbuild/protobuf/wkt";
|
|
15
|
-
import { SwarmRequestSchema, SwarmResponseSchema, TextMessageSchema } from "@dxos/protocols/buf/dxos/edge/messenger_pb";
|
|
16
|
-
|
|
17
|
-
// packages/core/mesh/edge-client/src/protocol.ts
|
|
18
|
-
import { invariant } from "@dxos/invariant";
|
|
19
|
-
import { buf, bufWkt } from "@dxos/protocols/buf";
|
|
17
|
+
import { buf } from "@dxos/protocols/buf";
|
|
20
18
|
import { MessageSchema } from "@dxos/protocols/buf/dxos/edge/messenger_pb";
|
|
21
|
-
import {
|
|
22
|
-
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/core/mesh/edge-client/src/protocol.ts";
|
|
23
|
-
var getTypename = (typeName) => `type.googleapis.com/${typeName}`;
|
|
24
|
-
var Protocol = class {
|
|
25
|
-
constructor(types) {
|
|
26
|
-
this._typeRegistry = buf.createRegistry(...types);
|
|
27
|
-
}
|
|
28
|
-
get typeRegistry() {
|
|
29
|
-
return this._typeRegistry;
|
|
30
|
-
}
|
|
31
|
-
toJson(message) {
|
|
32
|
-
try {
|
|
33
|
-
return buf.toJson(MessageSchema, message, {
|
|
34
|
-
registry: this.typeRegistry
|
|
35
|
-
});
|
|
36
|
-
} catch (err) {
|
|
37
|
-
return {
|
|
38
|
-
type: this.getPayloadType(message)
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Return the payload with the given type.
|
|
44
|
-
*/
|
|
45
|
-
getPayload(message, type) {
|
|
46
|
-
invariant(message.payload, void 0, {
|
|
47
|
-
F: __dxlog_file,
|
|
48
|
-
L: 40,
|
|
49
|
-
S: this,
|
|
50
|
-
A: [
|
|
51
|
-
"message.payload",
|
|
52
|
-
""
|
|
53
|
-
]
|
|
54
|
-
});
|
|
55
|
-
const payloadTypename = this.getPayloadType(message);
|
|
56
|
-
if (type && type.typeName !== payloadTypename) {
|
|
57
|
-
throw new Error(`Unexpected payload type: ${payloadTypename}; expected ${type.typeName}`);
|
|
58
|
-
}
|
|
59
|
-
invariant(bufWkt.anyIs(message.payload, type), `Unexpected payload type: ${payloadTypename}}`, {
|
|
60
|
-
F: __dxlog_file,
|
|
61
|
-
L: 46,
|
|
62
|
-
S: this,
|
|
63
|
-
A: [
|
|
64
|
-
"bufWkt.anyIs(message.payload, type)",
|
|
65
|
-
"`Unexpected payload type: ${payloadTypename}}`"
|
|
66
|
-
]
|
|
67
|
-
});
|
|
68
|
-
const payload = bufWkt.anyUnpack(message.payload, this.typeRegistry);
|
|
69
|
-
invariant(payload, `Empty payload: ${payloadTypename}}`, {
|
|
70
|
-
F: __dxlog_file,
|
|
71
|
-
L: 48,
|
|
72
|
-
S: this,
|
|
73
|
-
A: [
|
|
74
|
-
"payload",
|
|
75
|
-
"`Empty payload: ${payloadTypename}}`"
|
|
76
|
-
]
|
|
77
|
-
});
|
|
78
|
-
return payload;
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Get the payload type.
|
|
82
|
-
*/
|
|
83
|
-
getPayloadType(message) {
|
|
84
|
-
if (!message.payload) {
|
|
85
|
-
return void 0;
|
|
86
|
-
}
|
|
87
|
-
const [, type] = message.payload.typeUrl.split("/");
|
|
88
|
-
return type;
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
|
-
* Create a packed message.
|
|
92
|
-
*/
|
|
93
|
-
createMessage(type, { source, target, payload, serviceId }) {
|
|
94
|
-
return buf.create(MessageSchema, {
|
|
95
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
96
|
-
source,
|
|
97
|
-
target,
|
|
98
|
-
serviceId,
|
|
99
|
-
payload: payload ? bufWkt.anyPack(type, buf.create(type, payload)) : void 0
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
};
|
|
103
|
-
var toUint8Array = async (data) => {
|
|
104
|
-
if (data instanceof Buffer) {
|
|
105
|
-
return bufferToArray(data);
|
|
106
|
-
}
|
|
107
|
-
if (data instanceof Blob) {
|
|
108
|
-
return new Uint8Array(await data.arrayBuffer());
|
|
109
|
-
}
|
|
110
|
-
throw new Error(`Unexpected datatype: ${data}`);
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
// packages/core/mesh/edge-client/src/defs.ts
|
|
114
|
-
var protocol = new Protocol([
|
|
115
|
-
SwarmRequestSchema,
|
|
116
|
-
SwarmResponseSchema,
|
|
117
|
-
TextMessageSchema,
|
|
118
|
-
AnySchema
|
|
119
|
-
]);
|
|
19
|
+
import { schema } from "@dxos/protocols/proto";
|
|
120
20
|
|
|
121
21
|
// packages/core/mesh/edge-client/src/errors.ts
|
|
122
|
-
var
|
|
22
|
+
var EdgeConnectionClosedError = class extends Error {
|
|
23
|
+
constructor() {
|
|
24
|
+
super("Edge connection closed.");
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
var EdgeIdentityChangedError = class extends Error {
|
|
123
28
|
constructor() {
|
|
124
|
-
super("
|
|
29
|
+
super("Edge identity changed.");
|
|
125
30
|
}
|
|
126
31
|
};
|
|
127
32
|
|
|
@@ -136,7 +41,7 @@ function _ts_decorate(decorators, target, key, desc) {
|
|
|
136
41
|
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;
|
|
137
42
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
138
43
|
}
|
|
139
|
-
var
|
|
44
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/core/mesh/edge-client/src/persistent-lifecycle.ts";
|
|
140
45
|
var INIT_RESTART_DELAY = 100;
|
|
141
46
|
var DEFAULT_MAX_RESTART_DELAY = 5e3;
|
|
142
47
|
var PersistentLifecycle = class extends Resource {
|
|
@@ -157,7 +62,7 @@ var PersistentLifecycle = class extends Resource {
|
|
|
157
62
|
log.warn("Restart failed", {
|
|
158
63
|
err
|
|
159
64
|
}, {
|
|
160
|
-
F:
|
|
65
|
+
F: __dxlog_file,
|
|
161
66
|
L: 64,
|
|
162
67
|
S: this,
|
|
163
68
|
C: (f, a) => f(...a)
|
|
@@ -169,7 +74,7 @@ var PersistentLifecycle = class extends Resource {
|
|
|
169
74
|
log.warn("Start failed", {
|
|
170
75
|
err
|
|
171
76
|
}, {
|
|
172
|
-
F:
|
|
77
|
+
F: __dxlog_file,
|
|
173
78
|
L: 69,
|
|
174
79
|
S: this,
|
|
175
80
|
C: (f, a) => f(...a)
|
|
@@ -186,7 +91,7 @@ var PersistentLifecycle = class extends Resource {
|
|
|
186
91
|
log(`restarting in ${this._restartAfter}ms`, {
|
|
187
92
|
state: this._lifecycleState
|
|
188
93
|
}, {
|
|
189
|
-
F:
|
|
94
|
+
F: __dxlog_file,
|
|
190
95
|
L: 81,
|
|
191
96
|
S: this,
|
|
192
97
|
C: (f, a) => f(...a)
|
|
@@ -218,17 +123,26 @@ _ts_decorate([
|
|
|
218
123
|
synchronized
|
|
219
124
|
], PersistentLifecycle.prototype, "scheduleRestart", null);
|
|
220
125
|
|
|
126
|
+
// packages/core/mesh/edge-client/src/utils.ts
|
|
127
|
+
var getEdgeUrlWithProtocol = (baseUrl, protocol2) => {
|
|
128
|
+
const isSecure = baseUrl.startsWith("https") || baseUrl.startsWith("wss");
|
|
129
|
+
const url = new URL(baseUrl);
|
|
130
|
+
url.protocol = protocol2 + (isSecure ? "s" : "");
|
|
131
|
+
return url.toString();
|
|
132
|
+
};
|
|
133
|
+
|
|
221
134
|
// packages/core/mesh/edge-client/src/edge-client.ts
|
|
222
|
-
var
|
|
135
|
+
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/core/mesh/edge-client/src/edge-client.ts";
|
|
223
136
|
var DEFAULT_TIMEOUT = 1e4;
|
|
224
137
|
var SIGNAL_KEEPALIVE_INTERVAL = 5e3;
|
|
138
|
+
var DISABLE_AUTH = true;
|
|
225
139
|
var EdgeClient = class extends Resource2 {
|
|
226
|
-
constructor(
|
|
140
|
+
constructor(_identity, _config) {
|
|
227
141
|
super();
|
|
228
|
-
this.
|
|
229
|
-
this._peerKey = _peerKey;
|
|
142
|
+
this._identity = _identity;
|
|
230
143
|
this._config = _config;
|
|
231
144
|
this.reconnect = new Event();
|
|
145
|
+
this.connected = new Event();
|
|
232
146
|
this._persistentLifecycle = new PersistentLifecycle({
|
|
233
147
|
start: async () => this._openWebSocket(),
|
|
234
148
|
stop: async () => this._closeWebSocket(),
|
|
@@ -239,25 +153,27 @@ var EdgeClient = class extends Resource2 {
|
|
|
239
153
|
this._ws = void 0;
|
|
240
154
|
this._keepaliveCtx = void 0;
|
|
241
155
|
this._heartBeatContext = void 0;
|
|
242
|
-
this.
|
|
156
|
+
this._baseUrl = getEdgeUrlWithProtocol(_config.socketEndpoint, "ws");
|
|
243
157
|
}
|
|
244
158
|
// TODO(burdon): Attach logging.
|
|
245
159
|
get info() {
|
|
246
160
|
return {
|
|
247
161
|
open: this.isOpen,
|
|
248
|
-
identity: this.
|
|
249
|
-
device: this.
|
|
162
|
+
identity: this._identity.identityKey,
|
|
163
|
+
device: this._identity.peerKey
|
|
250
164
|
};
|
|
251
165
|
}
|
|
166
|
+
get isConnected() {
|
|
167
|
+
return Boolean(this._ws) && this._ready.state === TriggerState.RESOLVED;
|
|
168
|
+
}
|
|
252
169
|
get identityKey() {
|
|
253
|
-
return this.
|
|
170
|
+
return this._identity.identityKey;
|
|
254
171
|
}
|
|
255
172
|
get peerKey() {
|
|
256
|
-
return this.
|
|
173
|
+
return this._identity.peerKey;
|
|
257
174
|
}
|
|
258
|
-
setIdentity(
|
|
259
|
-
this.
|
|
260
|
-
this._identityKey = identityKey;
|
|
175
|
+
setIdentity(identity) {
|
|
176
|
+
this._identity = identity;
|
|
261
177
|
this._persistentLifecycle.scheduleRestart();
|
|
262
178
|
}
|
|
263
179
|
addListener(listener) {
|
|
@@ -271,8 +187,8 @@ var EdgeClient = class extends Resource2 {
|
|
|
271
187
|
log2("opening...", {
|
|
272
188
|
info: this.info
|
|
273
189
|
}, {
|
|
274
|
-
F:
|
|
275
|
-
L:
|
|
190
|
+
F: __dxlog_file2,
|
|
191
|
+
L: 123,
|
|
276
192
|
S: this,
|
|
277
193
|
C: (f, a) => f(...a)
|
|
278
194
|
});
|
|
@@ -280,8 +196,8 @@ var EdgeClient = class extends Resource2 {
|
|
|
280
196
|
log2.warn("Error while opening connection", {
|
|
281
197
|
err
|
|
282
198
|
}, {
|
|
283
|
-
F:
|
|
284
|
-
L:
|
|
199
|
+
F: __dxlog_file2,
|
|
200
|
+
L: 125,
|
|
285
201
|
S: this,
|
|
286
202
|
C: (f, a) => f(...a)
|
|
287
203
|
});
|
|
@@ -292,31 +208,51 @@ var EdgeClient = class extends Resource2 {
|
|
|
292
208
|
*/
|
|
293
209
|
async _close() {
|
|
294
210
|
log2("closing...", {
|
|
295
|
-
peerKey: this.
|
|
211
|
+
peerKey: this._identity.peerKey
|
|
296
212
|
}, {
|
|
297
|
-
F:
|
|
298
|
-
L:
|
|
213
|
+
F: __dxlog_file2,
|
|
214
|
+
L: 133,
|
|
299
215
|
S: this,
|
|
300
216
|
C: (f, a) => f(...a)
|
|
301
217
|
});
|
|
302
218
|
await this._persistentLifecycle.close();
|
|
303
219
|
}
|
|
304
220
|
async _openWebSocket() {
|
|
305
|
-
|
|
306
|
-
|
|
221
|
+
let protocolHeader;
|
|
222
|
+
if (!DISABLE_AUTH) {
|
|
223
|
+
const challenge = randomBytes(32);
|
|
224
|
+
const credential = await this._identity.presentCredentials({
|
|
225
|
+
challenge
|
|
226
|
+
});
|
|
227
|
+
protocolHeader = encodePresentationIntoAuthHeader(credential);
|
|
228
|
+
}
|
|
229
|
+
const url = new URL(`/ws/${this._identity.identityKey}/${this._identity.peerKey}`, this._baseUrl);
|
|
230
|
+
log2("Opening websocket", {
|
|
231
|
+
url: url.toString(),
|
|
232
|
+
protocolHeader
|
|
233
|
+
}, {
|
|
234
|
+
F: __dxlog_file2,
|
|
235
|
+
L: 148,
|
|
236
|
+
S: this,
|
|
237
|
+
C: (f, a) => f(...a)
|
|
238
|
+
});
|
|
239
|
+
this._ws = new WebSocket(url, protocolHeader ? [
|
|
240
|
+
protocolHeader
|
|
241
|
+
] : []);
|
|
307
242
|
this._ws.onopen = () => {
|
|
308
243
|
log2("opened", this.info, {
|
|
309
|
-
F:
|
|
310
|
-
L:
|
|
244
|
+
F: __dxlog_file2,
|
|
245
|
+
L: 152,
|
|
311
246
|
S: this,
|
|
312
247
|
C: (f, a) => f(...a)
|
|
313
248
|
});
|
|
314
249
|
this._ready.wake();
|
|
250
|
+
this.connected.emit();
|
|
315
251
|
};
|
|
316
252
|
this._ws.onclose = () => {
|
|
317
253
|
log2("closed", this.info, {
|
|
318
|
-
F:
|
|
319
|
-
L:
|
|
254
|
+
F: __dxlog_file2,
|
|
255
|
+
L: 157,
|
|
320
256
|
S: this,
|
|
321
257
|
C: (f, a) => f(...a)
|
|
322
258
|
});
|
|
@@ -327,8 +263,8 @@ var EdgeClient = class extends Resource2 {
|
|
|
327
263
|
error: event.error,
|
|
328
264
|
info: event.message
|
|
329
265
|
}, {
|
|
330
|
-
F:
|
|
331
|
-
L:
|
|
266
|
+
F: __dxlog_file2,
|
|
267
|
+
L: 161,
|
|
332
268
|
S: this,
|
|
333
269
|
C: (f, a) => f(...a)
|
|
334
270
|
});
|
|
@@ -340,13 +276,13 @@ var EdgeClient = class extends Resource2 {
|
|
|
340
276
|
return;
|
|
341
277
|
}
|
|
342
278
|
const data = await toUint8Array(event.data);
|
|
343
|
-
const message =
|
|
279
|
+
const message = buf.fromBinary(MessageSchema, data);
|
|
344
280
|
log2("received", {
|
|
345
|
-
peerKey: this.
|
|
281
|
+
peerKey: this._identity.peerKey,
|
|
346
282
|
payload: protocol.getPayloadType(message)
|
|
347
283
|
}, {
|
|
348
|
-
F:
|
|
349
|
-
L:
|
|
284
|
+
F: __dxlog_file2,
|
|
285
|
+
L: 174,
|
|
350
286
|
S: this,
|
|
351
287
|
C: (f, a) => f(...a)
|
|
352
288
|
});
|
|
@@ -359,8 +295,8 @@ var EdgeClient = class extends Resource2 {
|
|
|
359
295
|
err,
|
|
360
296
|
payload: protocol.getPayloadType(message)
|
|
361
297
|
}, {
|
|
362
|
-
F:
|
|
363
|
-
L:
|
|
298
|
+
F: __dxlog_file2,
|
|
299
|
+
L: 180,
|
|
364
300
|
S: this,
|
|
365
301
|
C: (f, a) => f(...a)
|
|
366
302
|
});
|
|
@@ -372,8 +308,8 @@ var EdgeClient = class extends Resource2 {
|
|
|
372
308
|
timeout: this._config.timeout ?? DEFAULT_TIMEOUT
|
|
373
309
|
});
|
|
374
310
|
this._keepaliveCtx = new Context(void 0, {
|
|
375
|
-
F:
|
|
376
|
-
L:
|
|
311
|
+
F: __dxlog_file2,
|
|
312
|
+
L: 190
|
|
377
313
|
});
|
|
378
314
|
scheduleTaskInterval(this._keepaliveCtx, async () => {
|
|
379
315
|
this._ws?.send("__ping__");
|
|
@@ -386,7 +322,7 @@ var EdgeClient = class extends Resource2 {
|
|
|
386
322
|
return;
|
|
387
323
|
}
|
|
388
324
|
try {
|
|
389
|
-
this._ready.throw(new
|
|
325
|
+
this._ready.throw(this.isOpen ? new EdgeIdentityChangedError() : new EdgeConnectionClosedError());
|
|
390
326
|
this._ready.reset();
|
|
391
327
|
void this._keepaliveCtx?.dispose();
|
|
392
328
|
this._keepaliveCtx = void 0;
|
|
@@ -407,8 +343,8 @@ var EdgeClient = class extends Resource2 {
|
|
|
407
343
|
log2.warn("Error closing websocket", {
|
|
408
344
|
err
|
|
409
345
|
}, {
|
|
410
|
-
F:
|
|
411
|
-
L:
|
|
346
|
+
F: __dxlog_file2,
|
|
347
|
+
L: 226,
|
|
412
348
|
S: this,
|
|
413
349
|
C: (f, a) => f(...a)
|
|
414
350
|
});
|
|
@@ -420,38 +356,32 @@ var EdgeClient = class extends Resource2 {
|
|
|
420
356
|
*/
|
|
421
357
|
async send(message) {
|
|
422
358
|
if (this._ready.state !== TriggerState.RESOLVED) {
|
|
359
|
+
log2("waiting for websocket to become ready", void 0, {
|
|
360
|
+
F: __dxlog_file2,
|
|
361
|
+
L: 236,
|
|
362
|
+
S: this,
|
|
363
|
+
C: (f, a) => f(...a)
|
|
364
|
+
});
|
|
423
365
|
await this._ready.wait({
|
|
424
366
|
timeout: this._config.timeout ?? DEFAULT_TIMEOUT
|
|
425
367
|
});
|
|
426
368
|
}
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
""
|
|
434
|
-
]
|
|
435
|
-
});
|
|
436
|
-
invariant2(!message.source || message.source.peerKey === this._peerKey, void 0, {
|
|
437
|
-
F: __dxlog_file3,
|
|
438
|
-
L: 203,
|
|
439
|
-
S: this,
|
|
440
|
-
A: [
|
|
441
|
-
"!message.source || message.source.peerKey === this._peerKey",
|
|
442
|
-
""
|
|
443
|
-
]
|
|
444
|
-
});
|
|
369
|
+
if (!this._ws) {
|
|
370
|
+
throw new EdgeConnectionClosedError();
|
|
371
|
+
}
|
|
372
|
+
if (message.source && (message.source.peerKey !== this._identity.peerKey || message.source.identityKey !== this.identityKey)) {
|
|
373
|
+
throw new EdgeIdentityChangedError();
|
|
374
|
+
}
|
|
445
375
|
log2("sending...", {
|
|
446
|
-
peerKey: this.
|
|
376
|
+
peerKey: this._identity.peerKey,
|
|
447
377
|
payload: protocol.getPayloadType(message)
|
|
448
378
|
}, {
|
|
449
|
-
F:
|
|
450
|
-
L:
|
|
379
|
+
F: __dxlog_file2,
|
|
380
|
+
L: 249,
|
|
451
381
|
S: this,
|
|
452
382
|
C: (f, a) => f(...a)
|
|
453
383
|
});
|
|
454
|
-
this._ws.send(
|
|
384
|
+
this._ws.send(buf.toBinary(MessageSchema, message));
|
|
455
385
|
}
|
|
456
386
|
_onHeartbeat() {
|
|
457
387
|
if (this._lifecycleState !== LifecycleState2.OPEN) {
|
|
@@ -459,17 +389,256 @@ var EdgeClient = class extends Resource2 {
|
|
|
459
389
|
}
|
|
460
390
|
void this._heartBeatContext?.dispose();
|
|
461
391
|
this._heartBeatContext = new Context(void 0, {
|
|
462
|
-
F:
|
|
463
|
-
L:
|
|
392
|
+
F: __dxlog_file2,
|
|
393
|
+
L: 258
|
|
464
394
|
});
|
|
465
395
|
scheduleTask(this._heartBeatContext, () => {
|
|
466
396
|
this._persistentLifecycle.scheduleRestart();
|
|
467
397
|
}, 2 * SIGNAL_KEEPALIVE_INTERVAL);
|
|
468
398
|
}
|
|
469
399
|
};
|
|
400
|
+
var encodePresentationIntoAuthHeader = (presentation) => {
|
|
401
|
+
const encoded = schema.getCodecForType("dxos.halo.credentials.Presentation").encode(presentation);
|
|
402
|
+
const encodedToken = Buffer.from(encoded).toString("base64").replace(/=*$/, "").replaceAll("/", "|");
|
|
403
|
+
return `base64url.bearer.authorization.dxos.org.${encodedToken}`;
|
|
404
|
+
};
|
|
405
|
+
|
|
406
|
+
// packages/core/mesh/edge-client/src/auth.ts
|
|
407
|
+
import { createCredential, signPresentation } from "@dxos/credentials";
|
|
408
|
+
import { Keyring } from "@dxos/keyring";
|
|
409
|
+
import { PublicKey } from "@dxos/keys";
|
|
410
|
+
var createDeviceEdgeIdentity = async (signer, key) => {
|
|
411
|
+
return {
|
|
412
|
+
identityKey: key.toHex(),
|
|
413
|
+
peerKey: key.toHex(),
|
|
414
|
+
presentCredentials: async ({ challenge }) => {
|
|
415
|
+
return signPresentation({
|
|
416
|
+
presentation: {
|
|
417
|
+
credentials: [
|
|
418
|
+
// Verifier requires at least one credential in the presentation to establish the subject.
|
|
419
|
+
await createCredential({
|
|
420
|
+
assertion: {
|
|
421
|
+
"@type": "dxos.halo.credentials.Auth"
|
|
422
|
+
},
|
|
423
|
+
issuer: key,
|
|
424
|
+
subject: key,
|
|
425
|
+
signer
|
|
426
|
+
})
|
|
427
|
+
]
|
|
428
|
+
},
|
|
429
|
+
signer,
|
|
430
|
+
signerKey: key,
|
|
431
|
+
nonce: challenge
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
};
|
|
435
|
+
};
|
|
436
|
+
var createChainEdgeIdentity = async (signer, identityKey, peerKey, chain, credentials) => {
|
|
437
|
+
const credentialsToSign = credentials.length > 0 ? credentials : [
|
|
438
|
+
await createCredential({
|
|
439
|
+
assertion: {
|
|
440
|
+
"@type": "dxos.halo.credentials.Auth"
|
|
441
|
+
},
|
|
442
|
+
issuer: identityKey,
|
|
443
|
+
subject: identityKey,
|
|
444
|
+
signer,
|
|
445
|
+
chain,
|
|
446
|
+
signingKey: peerKey
|
|
447
|
+
})
|
|
448
|
+
];
|
|
449
|
+
return {
|
|
450
|
+
identityKey: identityKey.toHex(),
|
|
451
|
+
peerKey: peerKey.toHex(),
|
|
452
|
+
presentCredentials: async ({ challenge }) => {
|
|
453
|
+
return signPresentation({
|
|
454
|
+
presentation: {
|
|
455
|
+
credentials: credentialsToSign
|
|
456
|
+
},
|
|
457
|
+
signer,
|
|
458
|
+
nonce: challenge,
|
|
459
|
+
signerKey: peerKey,
|
|
460
|
+
chain
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
};
|
|
464
|
+
};
|
|
465
|
+
var createEphemeralEdgeIdentity = async () => {
|
|
466
|
+
const keyring = new Keyring();
|
|
467
|
+
const key = await keyring.createKey();
|
|
468
|
+
return createDeviceEdgeIdentity(keyring, key);
|
|
469
|
+
};
|
|
470
|
+
var createTestHaloEdgeIdentity = async (signer, identityKey, deviceKey) => {
|
|
471
|
+
const deviceAdmission = await createCredential({
|
|
472
|
+
assertion: {
|
|
473
|
+
"@type": "dxos.halo.credentials.AuthorizedDevice",
|
|
474
|
+
deviceKey,
|
|
475
|
+
identityKey
|
|
476
|
+
},
|
|
477
|
+
issuer: identityKey,
|
|
478
|
+
subject: deviceKey,
|
|
479
|
+
signer
|
|
480
|
+
});
|
|
481
|
+
return createChainEdgeIdentity(signer, identityKey, deviceKey, {
|
|
482
|
+
credential: deviceAdmission
|
|
483
|
+
}, [
|
|
484
|
+
await createCredential({
|
|
485
|
+
assertion: {
|
|
486
|
+
"@type": "dxos.halo.credentials.Auth"
|
|
487
|
+
},
|
|
488
|
+
issuer: identityKey,
|
|
489
|
+
subject: identityKey,
|
|
490
|
+
signer
|
|
491
|
+
})
|
|
492
|
+
]);
|
|
493
|
+
};
|
|
494
|
+
var createStubEdgeIdentity = () => {
|
|
495
|
+
const identityKey = PublicKey.random();
|
|
496
|
+
const deviceKey = PublicKey.random();
|
|
497
|
+
return {
|
|
498
|
+
identityKey: identityKey.toHex(),
|
|
499
|
+
peerKey: deviceKey.toHex(),
|
|
500
|
+
presentCredentials: async () => {
|
|
501
|
+
throw new Error("Stub identity does not support authentication.");
|
|
502
|
+
}
|
|
503
|
+
};
|
|
504
|
+
};
|
|
505
|
+
|
|
506
|
+
// packages/core/mesh/edge-client/src/edge-http-client.ts
|
|
507
|
+
import { sleep as sleep2 } from "@dxos/async";
|
|
508
|
+
import { Context as Context2 } from "@dxos/context";
|
|
509
|
+
import { log as log3 } from "@dxos/log";
|
|
510
|
+
import { EdgeCallFailedError } from "@dxos/protocols";
|
|
511
|
+
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/core/mesh/edge-client/src/edge-http-client.ts";
|
|
512
|
+
var DEFAULT_RETRY_TIMEOUT = 1500;
|
|
513
|
+
var DEFAULT_RETRY_JITTER = 500;
|
|
514
|
+
var DEFAULT_MAX_RETRIES_COUNT = 3;
|
|
515
|
+
var EdgeHttpClient = class {
|
|
516
|
+
constructor(baseUrl) {
|
|
517
|
+
this._baseUrl = getEdgeUrlWithProtocol(baseUrl, "http");
|
|
518
|
+
log3("created", {
|
|
519
|
+
url: this._baseUrl
|
|
520
|
+
}, {
|
|
521
|
+
F: __dxlog_file3,
|
|
522
|
+
L: 27,
|
|
523
|
+
S: this,
|
|
524
|
+
C: (f, a) => f(...a)
|
|
525
|
+
});
|
|
526
|
+
}
|
|
527
|
+
getCredentialsForNotarization(spaceId, args) {
|
|
528
|
+
return this._call(`/spaces/${spaceId}/notarization`, {
|
|
529
|
+
...args,
|
|
530
|
+
method: "GET"
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
async notarizeCredentials(spaceId, body, args) {
|
|
534
|
+
await this._call(`/spaces/${spaceId}/notarization`, {
|
|
535
|
+
...args,
|
|
536
|
+
body,
|
|
537
|
+
method: "POST"
|
|
538
|
+
});
|
|
539
|
+
}
|
|
540
|
+
async _call(path, args) {
|
|
541
|
+
const requestContext = args.context ?? new Context2(void 0, {
|
|
542
|
+
F: __dxlog_file3,
|
|
543
|
+
L: 43
|
|
544
|
+
});
|
|
545
|
+
const shouldRetry = createRetryHandler(args);
|
|
546
|
+
const request = createRequest(args);
|
|
547
|
+
const url = `${this._baseUrl}${path.startsWith("/") ? path.slice(1) : path}`;
|
|
548
|
+
log3.info("call", {
|
|
549
|
+
method: args.method,
|
|
550
|
+
path
|
|
551
|
+
}, {
|
|
552
|
+
F: __dxlog_file3,
|
|
553
|
+
L: 48,
|
|
554
|
+
S: this,
|
|
555
|
+
C: (f, a) => f(...a)
|
|
556
|
+
});
|
|
557
|
+
while (true) {
|
|
558
|
+
let processingError;
|
|
559
|
+
let retryAfterHeaderValue = Number.NaN;
|
|
560
|
+
try {
|
|
561
|
+
const response = await fetch(url, request);
|
|
562
|
+
retryAfterHeaderValue = Number(response.headers.get("Retry-After"));
|
|
563
|
+
if (response.ok) {
|
|
564
|
+
const body = await response.json();
|
|
565
|
+
if (body.success) {
|
|
566
|
+
return body.data;
|
|
567
|
+
}
|
|
568
|
+
const isNonRetryable = body.errorData != null;
|
|
569
|
+
if (isNonRetryable) {
|
|
570
|
+
throw new EdgeCallFailedError(body.reason, body.errorData);
|
|
571
|
+
}
|
|
572
|
+
processingError = new EdgeCallFailedError(body.reason);
|
|
573
|
+
} else {
|
|
574
|
+
processingError = EdgeCallFailedError.fromFailureResponse(response);
|
|
575
|
+
if (!isRetryable(response.status)) {
|
|
576
|
+
throw processingError;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
} catch (error) {
|
|
580
|
+
processingError = EdgeCallFailedError.fromProcessingFailureCause(error);
|
|
581
|
+
}
|
|
582
|
+
if (await shouldRetry(requestContext, retryAfterHeaderValue)) {
|
|
583
|
+
log3.info("retrying edge request", {
|
|
584
|
+
path,
|
|
585
|
+
processingError
|
|
586
|
+
}, {
|
|
587
|
+
F: __dxlog_file3,
|
|
588
|
+
L: 81,
|
|
589
|
+
S: this,
|
|
590
|
+
C: (f, a) => f(...a)
|
|
591
|
+
});
|
|
592
|
+
} else {
|
|
593
|
+
throw processingError;
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
};
|
|
598
|
+
var createRequest = (args) => {
|
|
599
|
+
return {
|
|
600
|
+
method: args.method,
|
|
601
|
+
body: args.body && JSON.stringify(args.body)
|
|
602
|
+
};
|
|
603
|
+
};
|
|
604
|
+
var isRetryable = (status) => {
|
|
605
|
+
if (status === 501) {
|
|
606
|
+
return false;
|
|
607
|
+
}
|
|
608
|
+
return !(status >= 400 && status < 500);
|
|
609
|
+
};
|
|
610
|
+
var createRetryHandler = (args) => {
|
|
611
|
+
if (!args.retry || args.retry.count < 1) {
|
|
612
|
+
return async () => false;
|
|
613
|
+
}
|
|
614
|
+
let retries = 0;
|
|
615
|
+
const maxRetries = args.retry.count ?? DEFAULT_MAX_RETRIES_COUNT;
|
|
616
|
+
const baseTimeout = args.retry.timeout ?? DEFAULT_RETRY_TIMEOUT;
|
|
617
|
+
const jitter = args.retry.jitter ?? DEFAULT_RETRY_JITTER;
|
|
618
|
+
return async (ctx, retryAfter) => {
|
|
619
|
+
if (++retries > maxRetries || ctx.disposed) {
|
|
620
|
+
return false;
|
|
621
|
+
}
|
|
622
|
+
if (retryAfter) {
|
|
623
|
+
await sleep2(retryAfter);
|
|
624
|
+
} else {
|
|
625
|
+
const timeout = baseTimeout + Math.random() * jitter;
|
|
626
|
+
await sleep2(timeout);
|
|
627
|
+
}
|
|
628
|
+
return true;
|
|
629
|
+
};
|
|
630
|
+
};
|
|
470
631
|
export {
|
|
471
632
|
EdgeClient,
|
|
633
|
+
EdgeConnectionClosedError,
|
|
634
|
+
EdgeHttpClient,
|
|
635
|
+
EdgeIdentityChangedError,
|
|
472
636
|
Protocol,
|
|
637
|
+
createChainEdgeIdentity,
|
|
638
|
+
createDeviceEdgeIdentity,
|
|
639
|
+
createEphemeralEdgeIdentity,
|
|
640
|
+
createStubEdgeIdentity,
|
|
641
|
+
createTestHaloEdgeIdentity,
|
|
473
642
|
getTypename,
|
|
474
643
|
protocol,
|
|
475
644
|
toUint8Array
|