@dxos/edge-client 0.6.9 → 0.6.10-main.3cfcc89

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/lib/browser/index.mjs +276 -138
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node/index.cjs +263 -129
  5. package/dist/lib/node/index.cjs.map +4 -4
  6. package/dist/lib/node/meta.json +1 -1
  7. package/dist/types/src/{client.d.ts → edge-client.d.ts} +21 -16
  8. package/dist/types/src/edge-client.d.ts.map +1 -0
  9. package/dist/types/src/edge-client.test.d.ts +2 -0
  10. package/dist/types/src/edge-client.test.d.ts.map +1 -0
  11. package/dist/types/src/errors.d.ts +4 -0
  12. package/dist/types/src/errors.d.ts.map +1 -0
  13. package/dist/types/src/index.d.ts +1 -1
  14. package/dist/types/src/index.d.ts.map +1 -1
  15. package/dist/types/src/persistent-lifecycle.d.ts +42 -0
  16. package/dist/types/src/persistent-lifecycle.d.ts.map +1 -0
  17. package/dist/types/src/persistent-lifecycle.test.d.ts +2 -0
  18. package/dist/types/src/persistent-lifecycle.test.d.ts.map +1 -0
  19. package/dist/types/src/test-utils.d.ts +11 -0
  20. package/dist/types/src/test-utils.d.ts.map +1 -0
  21. package/dist/types/src/websocket.test.d.ts +2 -0
  22. package/dist/types/src/websocket.test.d.ts.map +1 -0
  23. package/package.json +13 -9
  24. package/src/edge-client.test.ts +50 -0
  25. package/src/edge-client.ts +226 -0
  26. package/src/errors.ts +9 -0
  27. package/src/index.ts +1 -1
  28. package/src/persistent-lifecycle.test.ts +71 -0
  29. package/src/persistent-lifecycle.ts +106 -0
  30. package/src/protocol.test.ts +1 -1
  31. package/src/test-utils.ts +49 -0
  32. package/src/websocket.test.ts +35 -0
  33. package/dist/types/src/client.d.ts.map +0 -1
  34. package/src/client.ts +0 -179
@@ -1 +1 @@
1
- {"inputs":{"packages/core/mesh/edge-client/src/protocol.ts":{"bytes":10314,"imports":[{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/protocols/buf","kind":"import-statement","external":true},{"path":"@dxos/protocols/buf/dxos/edge/messenger_pb","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"format":"esm"},"packages/core/mesh/edge-client/src/defs.ts":{"bytes":1578,"imports":[{"path":"@bufbuild/protobuf/wkt","kind":"import-statement","external":true},{"path":"@dxos/protocols/buf/dxos/edge/messenger_pb","kind":"import-statement","external":true},{"path":"packages/core/mesh/edge-client/src/protocol.ts","kind":"import-statement","original":"./protocol"}],"format":"esm"},"packages/core/mesh/edge-client/src/client.ts":{"bytes":20675,"imports":[{"path":"isomorphic-ws","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/protocols/buf","kind":"import-statement","external":true},{"path":"@dxos/protocols/buf/dxos/edge/messenger_pb","kind":"import-statement","external":true},{"path":"packages/core/mesh/edge-client/src/defs.ts","kind":"import-statement","original":"./defs"},{"path":"packages/core/mesh/edge-client/src/protocol.ts","kind":"import-statement","original":"./protocol"}],"format":"esm"},"packages/core/mesh/edge-client/src/index.ts":{"bytes":836,"imports":[{"path":"@dxos/protocols/buf/dxos/edge/messenger_pb","kind":"import-statement","external":true},{"path":"packages/core/mesh/edge-client/src/client.ts","kind":"import-statement","original":"./client"},{"path":"packages/core/mesh/edge-client/src/defs.ts","kind":"import-statement","original":"./defs"},{"path":"packages/core/mesh/edge-client/src/protocol.ts","kind":"import-statement","original":"./protocol"}],"format":"esm"}},"outputs":{"packages/core/mesh/edge-client/dist/lib/browser/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":14946},"packages/core/mesh/edge-client/dist/lib/browser/index.mjs":{"imports":[{"path":"@dxos/protocols/buf/dxos/edge/messenger_pb","kind":"import-statement","external":true},{"path":"isomorphic-ws","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/protocols/buf","kind":"import-statement","external":true},{"path":"@dxos/protocols/buf/dxos/edge/messenger_pb","kind":"import-statement","external":true},{"path":"@bufbuild/protobuf/wkt","kind":"import-statement","external":true},{"path":"@dxos/protocols/buf/dxos/edge/messenger_pb","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/protocols/buf","kind":"import-statement","external":true},{"path":"@dxos/protocols/buf/dxos/edge/messenger_pb","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"exports":["EdgeClient","Protocol","getTypename","protocol","toUint8Array"],"entryPoint":"packages/core/mesh/edge-client/src/index.ts","inputs":{"packages/core/mesh/edge-client/src/index.ts":{"bytesInOutput":60},"packages/core/mesh/edge-client/src/client.ts":{"bytesInOutput":5789},"packages/core/mesh/edge-client/src/defs.ts":{"bytesInOutput":285},"packages/core/mesh/edge-client/src/protocol.ts":{"bytesInOutput":2600}},"bytes":9139}}}
1
+ {"inputs":{"packages/core/mesh/edge-client/src/protocol.ts":{"bytes":10314,"imports":[{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/protocols/buf","kind":"import-statement","external":true},{"path":"@dxos/protocols/buf/dxos/edge/messenger_pb","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"format":"esm"},"packages/core/mesh/edge-client/src/defs.ts":{"bytes":1578,"imports":[{"path":"@bufbuild/protobuf/wkt","kind":"import-statement","external":true},{"path":"@dxos/protocols/buf/dxos/edge/messenger_pb","kind":"import-statement","external":true},{"path":"packages/core/mesh/edge-client/src/protocol.ts","kind":"import-statement","original":"./protocol"}],"format":"esm"},"packages/core/mesh/edge-client/src/errors.ts":{"bytes":846,"imports":[],"format":"esm"},"packages/core/mesh/edge-client/src/persistent-lifecycle.ts":{"bytes":10868,"imports":[{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/debug","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true}],"format":"esm"},"packages/core/mesh/edge-client/src/edge-client.ts":{"bytes":26825,"imports":[{"path":"isomorphic-ws","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/protocols/buf","kind":"import-statement","external":true},{"path":"@dxos/protocols/buf/dxos/edge/messenger_pb","kind":"import-statement","external":true},{"path":"packages/core/mesh/edge-client/src/defs.ts","kind":"import-statement","original":"./defs"},{"path":"packages/core/mesh/edge-client/src/errors.ts","kind":"import-statement","original":"./errors"},{"path":"packages/core/mesh/edge-client/src/persistent-lifecycle.ts","kind":"import-statement","original":"./persistent-lifecycle"},{"path":"packages/core/mesh/edge-client/src/protocol.ts","kind":"import-statement","original":"./protocol"}],"format":"esm"},"packages/core/mesh/edge-client/src/index.ts":{"bytes":849,"imports":[{"path":"@dxos/protocols/buf/dxos/edge/messenger_pb","kind":"import-statement","external":true},{"path":"packages/core/mesh/edge-client/src/edge-client.ts","kind":"import-statement","original":"./edge-client"},{"path":"packages/core/mesh/edge-client/src/defs.ts","kind":"import-statement","original":"./defs"},{"path":"packages/core/mesh/edge-client/src/protocol.ts","kind":"import-statement","original":"./protocol"}],"format":"esm"}},"outputs":{"packages/core/mesh/edge-client/dist/lib/browser/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":23321},"packages/core/mesh/edge-client/dist/lib/browser/index.mjs":{"imports":[{"path":"@dxos/protocols/buf/dxos/edge/messenger_pb","kind":"import-statement","external":true},{"path":"isomorphic-ws","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/protocols/buf","kind":"import-statement","external":true},{"path":"@dxos/protocols/buf/dxos/edge/messenger_pb","kind":"import-statement","external":true},{"path":"@bufbuild/protobuf/wkt","kind":"import-statement","external":true},{"path":"@dxos/protocols/buf/dxos/edge/messenger_pb","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/protocols/buf","kind":"import-statement","external":true},{"path":"@dxos/protocols/buf/dxos/edge/messenger_pb","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/debug","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true}],"exports":["EdgeClient","Protocol","getTypename","protocol","toUint8Array"],"entryPoint":"packages/core/mesh/edge-client/src/index.ts","inputs":{"packages/core/mesh/edge-client/src/index.ts":{"bytesInOutput":60},"packages/core/mesh/edge-client/src/edge-client.ts":{"bytesInOutput":7041},"packages/core/mesh/edge-client/src/defs.ts":{"bytesInOutput":285},"packages/core/mesh/edge-client/src/protocol.ts":{"bytesInOutput":2600},"packages/core/mesh/edge-client/src/errors.ts":{"bytesInOutput":116},"packages/core/mesh/edge-client/src/persistent-lifecycle.ts":{"bytesInOutput":3041}},"bytes":13670}}}
@@ -50,6 +50,10 @@ var import_invariant2 = require("@dxos/invariant");
50
50
  var import_buf2 = require("@dxos/protocols/buf");
51
51
  var import_messenger_pb3 = require("@dxos/protocols/buf/dxos/edge/messenger_pb");
52
52
  var import_util = require("@dxos/util");
53
+ var import_async2 = require("@dxos/async");
54
+ var import_context2 = require("@dxos/context");
55
+ var import_debug = require("@dxos/debug");
56
+ var import_log2 = require("@dxos/log");
53
57
  var __dxlog_file = "/home/runner/work/dxos/dxos/packages/core/mesh/edge-client/src/protocol.ts";
54
58
  var getTypename = (typeName) => `type.googleapis.com/${typeName}`;
55
59
  var Protocol = class {
@@ -146,18 +150,122 @@ var protocol = new Protocol([
146
150
  import_messenger_pb2.TextMessageSchema,
147
151
  import_wkt.AnySchema
148
152
  ]);
149
- var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/core/mesh/edge-client/src/client.ts";
150
- var DEFAULT_TIMEOUT = 5e3;
153
+ var WebsocketClosedError = class extends Error {
154
+ constructor() {
155
+ super("WebSocket connection closed");
156
+ }
157
+ };
158
+ function _ts_decorate(decorators, target, key, desc) {
159
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
160
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
161
+ r = Reflect.decorate(decorators, target, key, desc);
162
+ else
163
+ for (var i = decorators.length - 1; i >= 0; i--)
164
+ if (d = decorators[i])
165
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
166
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
167
+ }
168
+ var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/core/mesh/edge-client/src/persistent-lifecycle.ts";
169
+ var INIT_RESTART_DELAY = 100;
170
+ var DEFAULT_MAX_RESTART_DELAY = 5e3;
171
+ var PersistentLifecycle = class extends import_context2.Resource {
172
+ constructor({ start, stop, onRestart, maxRestartDelay = DEFAULT_MAX_RESTART_DELAY }) {
173
+ super();
174
+ this._restartTask = void 0;
175
+ this._restartAfter = 0;
176
+ this._start = start;
177
+ this._stop = stop;
178
+ this._onRestart = onRestart;
179
+ this._maxRestartDelay = maxRestartDelay;
180
+ }
181
+ async _open() {
182
+ this._restartTask = new import_async2.DeferredTask(this._ctx, async () => {
183
+ try {
184
+ await this._restart();
185
+ } catch (err) {
186
+ import_log2.log.warn("Restart failed", {
187
+ err
188
+ }, {
189
+ F: __dxlog_file2,
190
+ L: 64,
191
+ S: this,
192
+ C: (f, a) => f(...a)
193
+ });
194
+ this._restartTask?.schedule();
195
+ }
196
+ });
197
+ await this._start().catch((err) => {
198
+ import_log2.log.warn("Start failed", {
199
+ err
200
+ }, {
201
+ F: __dxlog_file2,
202
+ L: 69,
203
+ S: this,
204
+ C: (f, a) => f(...a)
205
+ });
206
+ this._restartTask?.schedule();
207
+ });
208
+ }
209
+ async _close() {
210
+ await this._restartTask?.join();
211
+ await this._stop();
212
+ this._restartTask = void 0;
213
+ }
214
+ async _restart() {
215
+ (0, import_log2.log)(`restarting in ${this._restartAfter}ms`, {
216
+ state: this._lifecycleState
217
+ }, {
218
+ F: __dxlog_file2,
219
+ L: 81,
220
+ S: this,
221
+ C: (f, a) => f(...a)
222
+ });
223
+ await this._stop();
224
+ if (this._lifecycleState !== import_context2.LifecycleState.OPEN) {
225
+ return;
226
+ }
227
+ await (0, import_context2.cancelWithContext)(this._ctx, (0, import_async2.sleep)(this._restartAfter));
228
+ this._restartAfter = Math.min(Math.max(this._restartAfter * 2, INIT_RESTART_DELAY), this._maxRestartDelay);
229
+ await (0, import_debug.warnAfterTimeout)(5e3, "Connection establishment takes too long", () => this._start());
230
+ this._restartAfter = 0;
231
+ await this._onRestart?.();
232
+ }
233
+ /**
234
+ * Scheduling restart should be done from outside.
235
+ */
236
+ scheduleRestart() {
237
+ if (this._lifecycleState !== import_context2.LifecycleState.OPEN) {
238
+ return;
239
+ }
240
+ this._restartTask.schedule();
241
+ }
242
+ };
243
+ _ts_decorate([
244
+ import_async2.synchronized
245
+ ], PersistentLifecycle.prototype, "_open", null);
246
+ _ts_decorate([
247
+ import_async2.synchronized
248
+ ], PersistentLifecycle.prototype, "scheduleRestart", null);
249
+ var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/core/mesh/edge-client/src/edge-client.ts";
250
+ var DEFAULT_TIMEOUT = 1e4;
251
+ var SIGNAL_KEEPALIVE_INTERVAL = 5e3;
151
252
  var EdgeClient = class extends import_context.Resource {
152
- constructor(_identityKey, _deviceKey, _config) {
253
+ constructor(_identityKey, _peerKey, _config) {
153
254
  super();
154
255
  this._identityKey = _identityKey;
155
- this._deviceKey = _deviceKey;
256
+ this._peerKey = _peerKey;
156
257
  this._config = _config;
258
+ this.reconnect = new import_async.Event();
259
+ this._persistentLifecycle = new PersistentLifecycle({
260
+ start: async () => this._openWebSocket(),
261
+ stop: async () => this._closeWebSocket(),
262
+ onRestart: async () => this.reconnect.emit()
263
+ });
157
264
  this._listeners = /* @__PURE__ */ new Set();
158
- this._reconnect = void 0;
159
265
  this._ready = new import_async.Trigger();
160
266
  this._ws = void 0;
267
+ this._keepaliveCtx = void 0;
268
+ this._heartBeatContext = void 0;
161
269
  this._protocol = this._config.protocol ?? protocol;
162
270
  }
163
271
  // TODO(burdon): Attach logging.
@@ -165,29 +273,22 @@ var EdgeClient = class extends import_context.Resource {
165
273
  return {
166
274
  open: this.isOpen,
167
275
  identity: this._identityKey,
168
- device: this._deviceKey
276
+ device: this._peerKey
169
277
  };
170
278
  }
171
279
  get identityKey() {
172
280
  return this._identityKey;
173
281
  }
174
- get deviceKey() {
175
- return this._deviceKey;
282
+ get peerKey() {
283
+ return this._peerKey;
176
284
  }
177
285
  get isOpen() {
178
286
  return this._lifecycleState === import_context.LifecycleState.OPEN;
179
287
  }
180
- setIdentity({ deviceKey, identityKey }) {
181
- this._deviceKey = deviceKey;
288
+ setIdentity({ peerKey, identityKey }) {
289
+ this._peerKey = peerKey;
182
290
  this._identityKey = identityKey;
183
- this._reconnect = this._closeWebSocket().then(async () => {
184
- await this._openWebSocket();
185
- }).catch((err) => import_log.log.catch(err, void 0, {
186
- F: __dxlog_file2,
187
- L: 87,
188
- S: this,
189
- C: (f, a) => f(...a)
190
- }));
291
+ this._persistentLifecycle.scheduleRestart();
191
292
  }
192
293
  addListener(listener) {
193
294
  this._listeners.add(listener);
@@ -197,35 +298,23 @@ var EdgeClient = class extends import_context.Resource {
197
298
  * Open connection to messaging service.
198
299
  */
199
300
  async _open() {
200
- await this._reconnect;
201
- if (this._ws) {
202
- return;
203
- }
204
- (0, import_invariant.invariant)(this._deviceKey && this._identityKey, void 0, {
205
- F: __dxlog_file2,
206
- L: 103,
207
- S: this,
208
- A: [
209
- "this._deviceKey && this._identityKey",
210
- ""
211
- ]
212
- });
213
- import_log.log.info("opening...", {
301
+ (0, import_log.log)("opening...", {
214
302
  info: this.info
215
303
  }, {
216
- F: __dxlog_file2,
217
- L: 104,
304
+ F: __dxlog_file3,
305
+ L: 105,
218
306
  S: this,
219
307
  C: (f, a) => f(...a)
220
308
  });
221
- await this._openWebSocket();
222
- import_log.log.info("opened", {
223
- info: this.info
224
- }, {
225
- F: __dxlog_file2,
226
- L: 108,
227
- S: this,
228
- C: (f, a) => f(...a)
309
+ this._persistentLifecycle.open().catch((err) => {
310
+ import_log.log.warn("Error while opening connection", {
311
+ err
312
+ }, {
313
+ F: __dxlog_file3,
314
+ L: 107,
315
+ S: this,
316
+ C: (f, a) => f(...a)
317
+ });
229
318
  });
230
319
  }
231
320
  /**
@@ -233,135 +322,180 @@ var EdgeClient = class extends import_context.Resource {
233
322
  */
234
323
  async _close() {
235
324
  (0, import_log.log)("closing...", {
236
- deviceKey: this._deviceKey
325
+ peerKey: this._peerKey
237
326
  }, {
238
- F: __dxlog_file2,
327
+ F: __dxlog_file3,
239
328
  L: 115,
240
329
  S: this,
241
330
  C: (f, a) => f(...a)
242
331
  });
243
- await this._reconnect;
244
- await this._closeWebSocket();
245
- (0, import_log.log)("closed", {
246
- deviceKey: this._deviceKey
247
- }, {
248
- F: __dxlog_file2,
249
- L: 118,
250
- S: this,
251
- C: (f, a) => f(...a)
252
- });
332
+ await this._persistentLifecycle.close();
253
333
  }
254
334
  async _openWebSocket() {
255
- const url = new URL(`/ws/${this._identityKey.toHex()}/${this._deviceKey.toHex()}`, this._config.socketEndpoint);
335
+ const url = new URL(`/ws/${this._identityKey}/${this._peerKey}`, this._config.socketEndpoint);
256
336
  this._ws = new import_isomorphic_ws.default(url);
257
- Object.assign(this._ws, {
258
- onopen: () => {
259
- (0, import_log.log)("opened", this.info, {
260
- F: __dxlog_file2,
261
- L: 126,
262
- S: this,
263
- C: (f, a) => f(...a)
264
- });
265
- this._ready.wake();
266
- },
267
- onclose: () => {
268
- (0, import_log.log)("closed", this.info, {
269
- F: __dxlog_file2,
270
- L: 131,
271
- S: this,
272
- C: (f, a) => f(...a)
273
- });
274
- },
275
- onerror: (event) => {
276
- import_log.log.catch(event.error, this.info, {
277
- F: __dxlog_file2,
278
- L: 135,
279
- S: this,
280
- C: (f, a) => f(...a)
281
- });
282
- this._ready.throw(event.error);
283
- },
284
- /**
285
- * https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent/data
286
- */
287
- onmessage: async (event) => {
288
- const data = await toUint8Array(event.data);
289
- const message = import_buf.buf.fromBinary(import_messenger_pb.MessageSchema, data);
290
- (0, import_log.log)("received", {
291
- deviceKey: this._deviceKey,
292
- payload: protocol.getPayloadType(message)
293
- }, {
294
- F: __dxlog_file2,
295
- L: 145,
296
- S: this,
297
- C: (f, a) => f(...a)
298
- });
299
- if (message) {
300
- for (const listener of this._listeners) {
301
- try {
302
- await listener(message);
303
- } catch (err) {
304
- import_log.log.error("processing", {
305
- err,
306
- payload: protocol.getPayloadType(message)
307
- }, {
308
- F: __dxlog_file2,
309
- L: 151,
310
- S: this,
311
- C: (f, a) => f(...a)
312
- });
313
- }
337
+ this._ws.onopen = () => {
338
+ (0, import_log.log)("opened", this.info, {
339
+ F: __dxlog_file3,
340
+ L: 124,
341
+ S: this,
342
+ C: (f, a) => f(...a)
343
+ });
344
+ this._ready.wake();
345
+ };
346
+ this._ws.onclose = () => {
347
+ (0, import_log.log)("closed", this.info, {
348
+ F: __dxlog_file3,
349
+ L: 128,
350
+ S: this,
351
+ C: (f, a) => f(...a)
352
+ });
353
+ this._persistentLifecycle.scheduleRestart();
354
+ };
355
+ this._ws.onerror = (event) => {
356
+ import_log.log.warn("EdgeClient socket error", {
357
+ error: event.error,
358
+ info: event.message
359
+ }, {
360
+ F: __dxlog_file3,
361
+ L: 132,
362
+ S: this,
363
+ C: (f, a) => f(...a)
364
+ });
365
+ this._persistentLifecycle.scheduleRestart();
366
+ };
367
+ this._ws.onmessage = async (event) => {
368
+ if (event.data === "__pong__") {
369
+ this._onHeartbeat();
370
+ return;
371
+ }
372
+ const data = await toUint8Array(event.data);
373
+ const message = import_buf.buf.fromBinary(import_messenger_pb.MessageSchema, data);
374
+ (0, import_log.log)("received", {
375
+ peerKey: this._peerKey,
376
+ payload: protocol.getPayloadType(message)
377
+ }, {
378
+ F: __dxlog_file3,
379
+ L: 145,
380
+ S: this,
381
+ C: (f, a) => f(...a)
382
+ });
383
+ if (message) {
384
+ for (const listener of this._listeners) {
385
+ try {
386
+ await listener(message);
387
+ } catch (err) {
388
+ import_log.log.error("processing", {
389
+ err,
390
+ payload: protocol.getPayloadType(message)
391
+ }, {
392
+ F: __dxlog_file3,
393
+ L: 151,
394
+ S: this,
395
+ C: (f, a) => f(...a)
396
+ });
314
397
  }
315
398
  }
316
399
  }
317
- });
400
+ };
318
401
  await this._ready.wait({
319
402
  timeout: this._config.timeout ?? DEFAULT_TIMEOUT
320
403
  });
404
+ this._keepaliveCtx = new import_context.Context(void 0, {
405
+ F: __dxlog_file3,
406
+ L: 158
407
+ });
408
+ (0, import_async.scheduleTaskInterval)(this._keepaliveCtx, async () => {
409
+ this._ws?.send("__ping__");
410
+ }, SIGNAL_KEEPALIVE_INTERVAL);
411
+ this._ws.send("__ping__");
412
+ this._onHeartbeat();
321
413
  }
322
414
  async _closeWebSocket() {
323
- this._ready.reset();
324
- this._ws.close();
325
- this._ws = void 0;
415
+ if (!this._ws) {
416
+ return;
417
+ }
418
+ try {
419
+ this._ready.throw(new WebsocketClosedError());
420
+ this._ready.reset();
421
+ void this._keepaliveCtx?.dispose();
422
+ this._keepaliveCtx = void 0;
423
+ void this._heartBeatContext?.dispose();
424
+ this._heartBeatContext = void 0;
425
+ this._ws.onopen = () => {
426
+ };
427
+ this._ws.onclose = () => {
428
+ };
429
+ this._ws.onerror = () => {
430
+ };
431
+ this._ws.close();
432
+ this._ws = void 0;
433
+ } catch (err) {
434
+ if (err instanceof Error && err.message.includes("WebSocket is closed before the connection is established.")) {
435
+ return;
436
+ }
437
+ import_log.log.warn("Error closing websocket", {
438
+ err
439
+ }, {
440
+ F: __dxlog_file3,
441
+ L: 194,
442
+ S: this,
443
+ C: (f, a) => f(...a)
444
+ });
445
+ }
326
446
  }
327
447
  /**
328
448
  * Send message.
329
449
  * NOTE: The message is guaranteed to be delivered but the service must respond with a message to confirm processing.
330
450
  */
331
- // TODO(burdon): Implement ACK?
332
451
  async send(message) {
333
- await this._ready.wait({
334
- timeout: this._config.timeout ?? DEFAULT_TIMEOUT
335
- });
452
+ if (this._ready.state !== import_async.TriggerState.RESOLVED) {
453
+ await this._ready.wait({
454
+ timeout: this._config.timeout ?? DEFAULT_TIMEOUT
455
+ });
456
+ }
336
457
  (0, import_invariant.invariant)(this._ws, void 0, {
337
- F: __dxlog_file2,
338
- L: 174,
458
+ F: __dxlog_file3,
459
+ L: 206,
339
460
  S: this,
340
461
  A: [
341
462
  "this._ws",
342
463
  ""
343
464
  ]
344
465
  });
345
- (0, import_invariant.invariant)(!message.source || message.source.peerKey === this._deviceKey.toHex(), void 0, {
346
- F: __dxlog_file2,
347
- L: 175,
466
+ (0, import_invariant.invariant)(!message.source || message.source.peerKey === this._peerKey, void 0, {
467
+ F: __dxlog_file3,
468
+ L: 207,
348
469
  S: this,
349
470
  A: [
350
- "!message.source || message.source.peerKey === this._deviceKey.toHex()",
471
+ "!message.source || message.source.peerKey === this._peerKey",
351
472
  ""
352
473
  ]
353
474
  });
354
475
  (0, import_log.log)("sending...", {
355
- deviceKey: this._deviceKey,
476
+ peerKey: this._peerKey,
356
477
  payload: protocol.getPayloadType(message)
357
478
  }, {
358
- F: __dxlog_file2,
359
- L: 176,
479
+ F: __dxlog_file3,
480
+ L: 208,
360
481
  S: this,
361
482
  C: (f, a) => f(...a)
362
483
  });
363
484
  this._ws.send(import_buf.buf.toBinary(import_messenger_pb.MessageSchema, message));
364
485
  }
486
+ _onHeartbeat() {
487
+ if (this._lifecycleState !== import_context.LifecycleState.OPEN) {
488
+ return;
489
+ }
490
+ void this._heartBeatContext?.dispose();
491
+ this._heartBeatContext = new import_context.Context(void 0, {
492
+ F: __dxlog_file3,
493
+ L: 217
494
+ });
495
+ (0, import_async.scheduleTask)(this._heartBeatContext, () => {
496
+ this._persistentLifecycle.scheduleRestart();
497
+ }, 2 * SIGNAL_KEEPALIVE_INTERVAL);
498
+ }
365
499
  };
366
500
  // Annotate the CommonJS export names for ESM import in node:
367
501
  0 && (module.exports = {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../../src/index.ts", "../../../src/client.ts", "../../../src/defs.ts", "../../../src/protocol.ts"],
4
- "sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nexport * from '@dxos/protocols/buf/dxos/edge/messenger_pb';\n\nexport * from './client';\nexport * from './defs';\nexport * from './protocol';\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport WebSocket from 'isomorphic-ws';\n\nimport { Trigger } from '@dxos/async';\nimport { LifecycleState, Resource, type Lifecycle } from '@dxos/context';\nimport { invariant } from '@dxos/invariant';\nimport { type PublicKey } from '@dxos/keys';\nimport { log } from '@dxos/log';\nimport { buf } from '@dxos/protocols/buf';\nimport { type Message, MessageSchema } from '@dxos/protocols/buf/dxos/edge/messenger_pb';\n\nimport { protocol } from './defs';\nimport { type Protocol, toUint8Array } from './protocol';\n\nconst DEFAULT_TIMEOUT = 5_000;\n\nexport type MessageListener = (message: Message) => void | Promise<void>;\n\nexport interface EdgeConnection extends Required<Lifecycle> {\n get info(): any;\n get identityKey(): PublicKey;\n get deviceKey(): PublicKey;\n get isOpen(): boolean;\n setIdentity(params: { deviceKey: PublicKey; identityKey: PublicKey }): void;\n addListener(listener: MessageListener): () => void;\n send(message: Message): Promise<void>;\n}\n\nexport type MessengerConfig = {\n socketEndpoint: string;\n timeout?: number;\n protocol?: Protocol;\n};\n\n/**\n * Messenger client.\n */\n// TODO(dmaretskyi): Rename EdgeClient.\n// TODO(mykola): Handle reconnections.\nexport class EdgeClient extends Resource implements EdgeConnection {\n private readonly _listeners = new Set<MessageListener>();\n private _reconnect?: Promise<void> = undefined;\n private readonly _protocol: Protocol;\n private _ready = new Trigger();\n private _ws?: WebSocket = undefined;\n\n constructor(\n private _identityKey: PublicKey,\n private _deviceKey: PublicKey,\n private readonly _config: MessengerConfig,\n ) {\n super();\n this._protocol = this._config.protocol ?? protocol;\n }\n\n // TODO(burdon): Attach logging.\n public get info() {\n return {\n open: this.isOpen,\n identity: this._identityKey,\n device: this._deviceKey,\n };\n }\n\n get identityKey() {\n return this._identityKey;\n }\n\n get deviceKey() {\n return this._deviceKey;\n }\n\n public get isOpen() {\n return this._lifecycleState === LifecycleState.OPEN;\n }\n\n setIdentity({ deviceKey, identityKey }: { deviceKey: PublicKey; identityKey: PublicKey }) {\n this._deviceKey = deviceKey;\n this._identityKey = identityKey;\n this._reconnect = this._closeWebSocket()\n .then(async () => {\n await this._openWebSocket();\n })\n .catch((err) => log.catch(err));\n }\n\n public addListener(listener: MessageListener): () => void {\n this._listeners.add(listener);\n return () => this._listeners.delete(listener);\n }\n\n /**\n * Open connection to messaging service.\n */\n protected override async _open() {\n await this._reconnect;\n if (this._ws) {\n return;\n }\n invariant(this._deviceKey && this._identityKey);\n log.info('opening...', { info: this.info });\n\n // TODO: handle reconnects\n await this._openWebSocket();\n log.info('opened', { info: this.info });\n }\n\n /**\n * Close connection and free resources.\n */\n protected override async _close() {\n log('closing...', { deviceKey: this._deviceKey });\n await this._reconnect;\n await this._closeWebSocket();\n log('closed', { deviceKey: this._deviceKey });\n }\n\n private async _openWebSocket() {\n const url = new URL(`/ws/${this._identityKey.toHex()}/${this._deviceKey.toHex()}`, this._config.socketEndpoint);\n this._ws = new WebSocket(url);\n Object.assign<WebSocket, Partial<WebSocket>>(this._ws, {\n onopen: () => {\n log('opened', this.info);\n this._ready.wake();\n },\n\n onclose: () => {\n log('closed', this.info);\n },\n\n onerror: (event) => {\n log.catch(event.error, this.info);\n this._ready.throw(event.error);\n },\n\n /**\n * https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent/data\n */\n onmessage: async (event) => {\n const data = await toUint8Array(event.data);\n const message = buf.fromBinary(MessageSchema, data);\n log('received', { deviceKey: this._deviceKey, payload: protocol.getPayloadType(message) });\n if (message) {\n for (const listener of this._listeners) {\n try {\n await listener(message);\n } catch (err) {\n log.error('processing', { err, payload: protocol.getPayloadType(message) });\n }\n }\n }\n },\n });\n\n await this._ready.wait({ timeout: this._config.timeout ?? DEFAULT_TIMEOUT });\n }\n\n private async _closeWebSocket() {\n this._ready.reset();\n this._ws!.close();\n this._ws = undefined;\n }\n\n /**\n * Send message.\n * NOTE: The message is guaranteed to be delivered but the service must respond with a message to confirm processing.\n */\n // TODO(burdon): Implement ACK?\n public async send(message: Message): Promise<void> {\n await this._ready.wait({ timeout: this._config.timeout ?? DEFAULT_TIMEOUT });\n invariant(this._ws);\n invariant(!message.source || message.source.peerKey === this._deviceKey.toHex());\n log('sending...', { deviceKey: this._deviceKey, payload: protocol.getPayloadType(message) });\n this._ws.send(buf.toBinary(MessageSchema, message));\n }\n}\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { AnySchema } from '@bufbuild/protobuf/wkt';\n\nimport { SwarmRequestSchema, SwarmResponseSchema, TextMessageSchema } from '@dxos/protocols/buf/dxos/edge/messenger_pb';\n\nimport { Protocol } from './protocol';\n\nexport const protocol = new Protocol([SwarmRequestSchema, SwarmResponseSchema, TextMessageSchema, AnySchema]);\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { invariant } from '@dxos/invariant';\nimport { buf, bufWkt } from '@dxos/protocols/buf';\nimport { type Message, MessageSchema, type Peer as PeerProto } from '@dxos/protocols/buf/dxos/edge/messenger_pb';\nimport { bufferToArray } from '@dxos/util';\n\nexport type PeerData = Partial<PeerProto>;\n\nexport const getTypename = (typeName: string) => `type.googleapis.com/${typeName}`;\n\n/**\n * NOTE: The type registry should be extended with all message types.\n */\nexport class Protocol {\n private readonly _typeRegistry: buf.Registry;\n\n constructor(types: buf.DescMessage[]) {\n this._typeRegistry = buf.createRegistry(...types);\n }\n\n get typeRegistry(): buf.Registry {\n return this._typeRegistry;\n }\n\n toJson(message: Message): any {\n try {\n return buf.toJson(MessageSchema, message, { registry: this.typeRegistry });\n } catch (err) {\n return { type: this.getPayloadType(message) };\n }\n }\n\n /**\n * Return the payload with the given type.\n */\n getPayload<Desc extends buf.DescMessage>(message: Message, type: Desc): buf.MessageShape<Desc> {\n invariant(message.payload);\n const payloadTypename = this.getPayloadType(message);\n if (type && type.typeName !== payloadTypename) {\n throw new Error(`Unexpected payload type: ${payloadTypename}; expected ${type.typeName}`);\n }\n\n invariant(bufWkt.anyIs(message.payload, type), `Unexpected payload type: ${payloadTypename}}`);\n const payload = bufWkt.anyUnpack(message.payload, this.typeRegistry) as buf.MessageShape<Desc>;\n invariant(payload, `Empty payload: ${payloadTypename}}`);\n return payload;\n }\n\n /**\n * Get the payload type.\n */\n getPayloadType(message: Message): string | undefined {\n if (!message.payload) {\n return undefined;\n }\n\n const [, type] = message.payload.typeUrl.split('/');\n return type;\n }\n\n /**\n * Create a packed message.\n */\n createMessage<Desc extends buf.DescMessage>(\n type: Desc,\n {\n source,\n target,\n payload,\n serviceId,\n }: {\n source?: PeerData;\n target?: PeerData[];\n payload?: buf.MessageInitShape<Desc>;\n serviceId?: string;\n },\n ) {\n return buf.create(MessageSchema, {\n timestamp: new Date().toISOString(),\n source,\n target,\n serviceId,\n payload: payload ? bufWkt.anyPack(type, buf.create(type, payload)) : undefined,\n });\n }\n}\n\n/**\n * Convert websocket data to Uint8Array.\n */\nexport const toUint8Array = async (data: any): Promise<Uint8Array> => {\n // Node.\n if (data instanceof Buffer) {\n return bufferToArray(data);\n }\n\n // Browser.\n if (data instanceof Blob) {\n return new Uint8Array(await (data as Blob).arrayBuffer());\n }\n\n throw new Error(`Unexpected datatype: ${data}`);\n};\n"],
5
- "mappings": "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",
6
- "names": ["import_messenger_pb", "import_invariant", "import_buf", "getTypename", "typeName", "Protocol", "constructor", "types", "_typeRegistry", "buf", "createRegistry", "typeRegistry", "toJson", "message", "MessageSchema", "registry", "err", "type", "getPayloadType", "getPayload", "invariant", "payload", "payloadTypename", "Error", "bufWkt", "anyIs", "anyUnpack", "undefined", "typeUrl", "split", "createMessage", "source", "target", "serviceId", "create", "timestamp", "Date", "toISOString", "anyPack", "toUint8Array", "data", "Buffer", "bufferToArray", "Blob", "Uint8Array", "arrayBuffer", "protocol", "SwarmRequestSchema", "SwarmResponseSchema", "TextMessageSchema", "AnySchema", "DEFAULT_TIMEOUT", "EdgeClient", "Resource", "_identityKey", "_deviceKey", "_config", "_listeners", "Set", "_reconnect", "_ready", "Trigger", "_ws", "_protocol", "info", "open", "isOpen", "identity", "device", "identityKey", "deviceKey", "_lifecycleState", "LifecycleState", "OPEN", "setIdentity", "_closeWebSocket", "then", "_openWebSocket", "catch", "log", "addListener", "listener", "add", "delete", "_open", "_close", "url", "URL", "toHex", "socketEndpoint", "WebSocket", "Object", "assign", "onopen", "wake", "onclose", "onerror", "event", "error", "throw", "onmessage", "fromBinary", "wait", "timeout", "reset", "close", "send", "peerKey", "toBinary"]
3
+ "sources": ["../../../src/index.ts", "../../../src/edge-client.ts", "../../../src/defs.ts", "../../../src/protocol.ts", "../../../src/errors.ts", "../../../src/persistent-lifecycle.ts"],
4
+ "sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nexport * from '@dxos/protocols/buf/dxos/edge/messenger_pb';\n\nexport * from './edge-client';\nexport * from './defs';\nexport * from './protocol';\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport WebSocket from 'isomorphic-ws';\n\nimport { Trigger, Event, scheduleTaskInterval, scheduleTask, TriggerState } from '@dxos/async';\nimport { Context, LifecycleState, Resource, type Lifecycle } from '@dxos/context';\nimport { invariant } from '@dxos/invariant';\nimport { log } from '@dxos/log';\nimport { buf } from '@dxos/protocols/buf';\nimport { type Message, MessageSchema } from '@dxos/protocols/buf/dxos/edge/messenger_pb';\n\nimport { protocol } from './defs';\nimport { WebsocketClosedError } from './errors';\nimport { PersistentLifecycle } from './persistent-lifecycle';\nimport { type Protocol, toUint8Array } from './protocol';\n\nconst DEFAULT_TIMEOUT = 10_000;\nconst SIGNAL_KEEPALIVE_INTERVAL = 5_000;\n\nexport type MessageListener = (message: Message) => void | Promise<void>;\n\nexport interface EdgeConnection extends Required<Lifecycle> {\n reconnect: Event;\n\n get info(): any;\n get identityKey(): string;\n get peerKey(): string;\n get isOpen(): boolean;\n setIdentity(params: { peerKey: string; identityKey: string }): void;\n addListener(listener: MessageListener): () => void;\n send(message: Message): Promise<void>;\n}\n\nexport type MessengerConfig = {\n socketEndpoint: string;\n timeout?: number;\n protocol?: Protocol;\n};\n\n/**\n * Messenger client.\n */\nexport class EdgeClient extends Resource implements EdgeConnection {\n public reconnect = new Event();\n private readonly _persistentLifecycle = new PersistentLifecycle({\n start: async () => this._openWebSocket(),\n stop: async () => this._closeWebSocket(),\n onRestart: async () => this.reconnect.emit(),\n });\n\n private readonly _listeners = new Set<MessageListener>();\n private readonly _protocol: Protocol;\n private _ready = new Trigger();\n private _ws?: WebSocket = undefined;\n private _keepaliveCtx?: Context = undefined;\n private _heartBeatContext?: Context = undefined;\n\n constructor(\n private _identityKey: string,\n private _peerKey: string,\n private readonly _config: MessengerConfig,\n ) {\n super();\n this._protocol = this._config.protocol ?? protocol;\n }\n\n // TODO(burdon): Attach logging.\n public get info() {\n return {\n open: this.isOpen,\n identity: this._identityKey,\n device: this._peerKey,\n };\n }\n\n get identityKey() {\n return this._identityKey;\n }\n\n get peerKey() {\n return this._peerKey;\n }\n\n public get isOpen() {\n return this._lifecycleState === LifecycleState.OPEN;\n }\n\n setIdentity({ peerKey, identityKey }: { peerKey: string; identityKey: string }) {\n this._peerKey = peerKey;\n this._identityKey = identityKey;\n this._persistentLifecycle.scheduleRestart();\n }\n\n public addListener(listener: MessageListener): () => void {\n this._listeners.add(listener);\n return () => this._listeners.delete(listener);\n }\n\n /**\n * Open connection to messaging service.\n */\n protected override async _open() {\n log('opening...', { info: this.info });\n this._persistentLifecycle.open().catch((err) => {\n log.warn('Error while opening connection', { err });\n });\n }\n\n /**\n * Close connection and free resources.\n */\n protected override async _close() {\n log('closing...', { peerKey: this._peerKey });\n await this._persistentLifecycle.close();\n }\n\n private async _openWebSocket() {\n const url = new URL(`/ws/${this._identityKey}/${this._peerKey}`, this._config.socketEndpoint);\n this._ws = new WebSocket(url);\n\n this._ws.onopen = () => {\n log('opened', this.info);\n this._ready.wake();\n };\n this._ws.onclose = () => {\n log('closed', this.info);\n this._persistentLifecycle.scheduleRestart();\n };\n this._ws.onerror = (event) => {\n log.warn('EdgeClient socket error', { error: event.error, info: event.message });\n this._persistentLifecycle.scheduleRestart();\n };\n /**\n * https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent/data\n */\n this._ws.onmessage = async (event) => {\n if (event.data === '__pong__') {\n this._onHeartbeat();\n return;\n }\n const data = await toUint8Array(event.data);\n const message = buf.fromBinary(MessageSchema, data);\n log('received', { peerKey: this._peerKey, payload: protocol.getPayloadType(message) });\n if (message) {\n for (const listener of this._listeners) {\n try {\n await listener(message);\n } catch (err) {\n log.error('processing', { err, payload: protocol.getPayloadType(message) });\n }\n }\n }\n };\n\n await this._ready.wait({ timeout: this._config.timeout ?? DEFAULT_TIMEOUT });\n this._keepaliveCtx = new Context();\n scheduleTaskInterval(\n this._keepaliveCtx,\n async () => {\n // TODO(mykola): use RFC6455 ping/pong once implemented in the browser?\n // Cloudflare's worker responds to this `without interrupting hibernation`. https://developers.cloudflare.com/durable-objects/api/websockets/#setwebsocketautoresponse\n this._ws?.send('__ping__');\n },\n SIGNAL_KEEPALIVE_INTERVAL,\n );\n this._ws.send('__ping__');\n this._onHeartbeat();\n }\n\n private async _closeWebSocket() {\n if (!this._ws) {\n return;\n }\n try {\n this._ready.throw(new WebsocketClosedError());\n this._ready.reset();\n void this._keepaliveCtx?.dispose();\n this._keepaliveCtx = undefined;\n void this._heartBeatContext?.dispose();\n this._heartBeatContext = undefined;\n\n // NOTE: Remove event handlers to avoid scheduling restart.\n this._ws.onopen = () => {};\n this._ws.onclose = () => {};\n this._ws.onerror = () => {};\n this._ws.close();\n this._ws = undefined;\n } catch (err) {\n if (err instanceof Error && err.message.includes('WebSocket is closed before the connection is established.')) {\n return;\n }\n log.warn('Error closing websocket', { err });\n }\n }\n\n /**\n * Send message.\n * NOTE: The message is guaranteed to be delivered but the service must respond with a message to confirm processing.\n */\n public async send(message: Message): Promise<void> {\n if (this._ready.state !== TriggerState.RESOLVED) {\n await this._ready.wait({ timeout: this._config.timeout ?? DEFAULT_TIMEOUT });\n }\n invariant(this._ws);\n invariant(!message.source || message.source.peerKey === this._peerKey);\n log('sending...', { peerKey: this._peerKey, payload: protocol.getPayloadType(message) });\n this._ws.send(buf.toBinary(MessageSchema, message));\n }\n\n private _onHeartbeat() {\n if (this._lifecycleState !== LifecycleState.OPEN) {\n return;\n }\n void this._heartBeatContext?.dispose();\n this._heartBeatContext = new Context();\n scheduleTask(\n this._heartBeatContext,\n () => {\n this._persistentLifecycle.scheduleRestart();\n },\n 2 * SIGNAL_KEEPALIVE_INTERVAL,\n );\n }\n}\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { AnySchema } from '@bufbuild/protobuf/wkt';\n\nimport { SwarmRequestSchema, SwarmResponseSchema, TextMessageSchema } from '@dxos/protocols/buf/dxos/edge/messenger_pb';\n\nimport { Protocol } from './protocol';\n\nexport const protocol = new Protocol([SwarmRequestSchema, SwarmResponseSchema, TextMessageSchema, AnySchema]);\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { invariant } from '@dxos/invariant';\nimport { buf, bufWkt } from '@dxos/protocols/buf';\nimport { type Message, MessageSchema, type Peer as PeerProto } from '@dxos/protocols/buf/dxos/edge/messenger_pb';\nimport { bufferToArray } from '@dxos/util';\n\nexport type PeerData = Partial<PeerProto>;\n\nexport const getTypename = (typeName: string) => `type.googleapis.com/${typeName}`;\n\n/**\n * NOTE: The type registry should be extended with all message types.\n */\nexport class Protocol {\n private readonly _typeRegistry: buf.Registry;\n\n constructor(types: buf.DescMessage[]) {\n this._typeRegistry = buf.createRegistry(...types);\n }\n\n get typeRegistry(): buf.Registry {\n return this._typeRegistry;\n }\n\n toJson(message: Message): any {\n try {\n return buf.toJson(MessageSchema, message, { registry: this.typeRegistry });\n } catch (err) {\n return { type: this.getPayloadType(message) };\n }\n }\n\n /**\n * Return the payload with the given type.\n */\n getPayload<Desc extends buf.DescMessage>(message: Message, type: Desc): buf.MessageShape<Desc> {\n invariant(message.payload);\n const payloadTypename = this.getPayloadType(message);\n if (type && type.typeName !== payloadTypename) {\n throw new Error(`Unexpected payload type: ${payloadTypename}; expected ${type.typeName}`);\n }\n\n invariant(bufWkt.anyIs(message.payload, type), `Unexpected payload type: ${payloadTypename}}`);\n const payload = bufWkt.anyUnpack(message.payload, this.typeRegistry) as buf.MessageShape<Desc>;\n invariant(payload, `Empty payload: ${payloadTypename}}`);\n return payload;\n }\n\n /**\n * Get the payload type.\n */\n getPayloadType(message: Message): string | undefined {\n if (!message.payload) {\n return undefined;\n }\n\n const [, type] = message.payload.typeUrl.split('/');\n return type;\n }\n\n /**\n * Create a packed message.\n */\n createMessage<Desc extends buf.DescMessage>(\n type: Desc,\n {\n source,\n target,\n payload,\n serviceId,\n }: {\n source?: PeerData;\n target?: PeerData[];\n payload?: buf.MessageInitShape<Desc>;\n serviceId?: string;\n },\n ) {\n return buf.create(MessageSchema, {\n timestamp: new Date().toISOString(),\n source,\n target,\n serviceId,\n payload: payload ? bufWkt.anyPack(type, buf.create(type, payload)) : undefined,\n });\n }\n}\n\n/**\n * Convert websocket data to Uint8Array.\n */\nexport const toUint8Array = async (data: any): Promise<Uint8Array> => {\n // Node.\n if (data instanceof Buffer) {\n return bufferToArray(data);\n }\n\n // Browser.\n if (data instanceof Blob) {\n return new Uint8Array(await (data as Blob).arrayBuffer());\n }\n\n throw new Error(`Unexpected datatype: ${data}`);\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nexport class WebsocketClosedError extends Error {\n constructor() {\n super('WebSocket connection closed');\n }\n}\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { DeferredTask, sleep, synchronized } from '@dxos/async';\nimport { cancelWithContext, LifecycleState, Resource } from '@dxos/context';\nimport { warnAfterTimeout } from '@dxos/debug';\nimport { log } from '@dxos/log';\n\nconst INIT_RESTART_DELAY = 100;\nconst DEFAULT_MAX_RESTART_DELAY = 5000;\n\nexport type PersistentLifecycleParams = {\n /**\n * Create connection.\n * If promise resolves successfully, connection is considered established.\n */\n start: () => Promise<void>;\n\n /**\n * Reset connection to initial state.\n */\n stop: () => Promise<void>;\n\n /**\n * Called after successful start.\n */\n onRestart?: () => Promise<void>;\n\n /**\n * Maximum delay between restartion attempts.\n * Default: 5000ms\n */\n maxRestartDelay?: number;\n};\n\n/**\n * Handles restarts (e.g. persists connection).\n * Restarts are scheduled with exponential backoff.\n */\nexport class PersistentLifecycle extends Resource {\n private readonly _start: () => Promise<void>;\n private readonly _stop: () => Promise<void>;\n private readonly _onRestart?: () => Promise<void>;\n private readonly _maxRestartDelay: number;\n\n private _restartTask?: DeferredTask = undefined;\n private _restartAfter = 0;\n\n constructor({ start, stop, onRestart, maxRestartDelay = DEFAULT_MAX_RESTART_DELAY }: PersistentLifecycleParams) {\n super();\n this._start = start;\n this._stop = stop;\n this._onRestart = onRestart;\n this._maxRestartDelay = maxRestartDelay;\n }\n\n @synchronized\n protected override async _open() {\n this._restartTask = new DeferredTask(this._ctx, async () => {\n try {\n await this._restart();\n } catch (err) {\n log.warn('Restart failed', { err });\n this._restartTask?.schedule();\n }\n });\n await this._start().catch((err) => {\n log.warn('Start failed', { err });\n this._restartTask?.schedule();\n });\n }\n\n protected override async _close() {\n await this._restartTask?.join();\n await this._stop();\n this._restartTask = undefined;\n }\n\n private async _restart() {\n log(`restarting in ${this._restartAfter}ms`, { state: this._lifecycleState });\n await this._stop();\n if (this._lifecycleState !== LifecycleState.OPEN) {\n return;\n }\n await cancelWithContext(this._ctx!, sleep(this._restartAfter));\n this._restartAfter = Math.min(Math.max(this._restartAfter * 2, INIT_RESTART_DELAY), this._maxRestartDelay);\n\n // May fail if the connection is not established.\n await warnAfterTimeout(5_000, 'Connection establishment takes too long', () => this._start());\n\n this._restartAfter = 0;\n await this._onRestart?.();\n }\n\n /**\n * Scheduling restart should be done from outside.\n */\n @synchronized\n scheduleRestart() {\n if (this._lifecycleState !== LifecycleState.OPEN) {\n return;\n }\n this._restartTask!.schedule();\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["import_messenger_pb", "import_invariant", "import_buf", "import_async", "import_context", "import_log", "getTypename", "typeName", "Protocol", "constructor", "types", "_typeRegistry", "buf", "createRegistry", "typeRegistry", "toJson", "message", "MessageSchema", "registry", "err", "type", "getPayloadType", "getPayload", "invariant", "payload", "payloadTypename", "Error", "bufWkt", "anyIs", "anyUnpack", "undefined", "typeUrl", "split", "createMessage", "source", "target", "serviceId", "create", "timestamp", "Date", "toISOString", "anyPack", "toUint8Array", "data", "Buffer", "bufferToArray", "Blob", "Uint8Array", "arrayBuffer", "protocol", "SwarmRequestSchema", "SwarmResponseSchema", "TextMessageSchema", "AnySchema", "WebsocketClosedError", "INIT_RESTART_DELAY", "DEFAULT_MAX_RESTART_DELAY", "PersistentLifecycle", "Resource", "start", "stop", "onRestart", "maxRestartDelay", "_restartTask", "_restartAfter", "_start", "_stop", "_onRestart", "_maxRestartDelay", "_open", "DeferredTask", "_ctx", "_restart", "log", "warn", "schedule", "catch", "_close", "join", "state", "_lifecycleState", "LifecycleState", "OPEN", "cancelWithContext", "sleep", "Math", "min", "max", "warnAfterTimeout", "scheduleRestart", "synchronized", "DEFAULT_TIMEOUT", "SIGNAL_KEEPALIVE_INTERVAL", "EdgeClient", "_identityKey", "_peerKey", "_config", "reconnect", "Event", "_persistentLifecycle", "_openWebSocket", "_closeWebSocket", "emit", "_listeners", "Set", "_ready", "Trigger", "_ws", "_keepaliveCtx", "_heartBeatContext", "_protocol", "info", "open", "isOpen", "identity", "device", "identityKey", "peerKey", "setIdentity", "addListener", "listener", "add", "delete", "close", "url", "URL", "socketEndpoint", "WebSocket", "onopen", "wake", "onclose", "onerror", "event", "error", "onmessage", "_onHeartbeat", "fromBinary", "wait", "timeout", "Context", "scheduleTaskInterval", "send", "throw", "reset", "dispose", "includes", "TriggerState", "RESOLVED", "toBinary", "scheduleTask"]
7
7
  }