@dxos/edge-client 0.6.12-staging.e11e696 → 0.6.13-main.548ca8d

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.
@@ -162,10 +162,15 @@ _ts_decorate([
162
162
  _ts_decorate([
163
163
  import_async2.synchronized
164
164
  ], PersistentLifecycle.prototype, "scheduleRestart", null);
165
+ var getEdgeUrlWithProtocol = (baseUrl, protocol2) => {
166
+ const isSecure = baseUrl.startsWith("https") || baseUrl.startsWith("wss");
167
+ const url = new URL(baseUrl);
168
+ url.protocol = protocol2 + (isSecure ? "s" : "");
169
+ return url.toString();
170
+ };
165
171
  var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/core/mesh/edge-client/src/edge-client.ts";
166
172
  var DEFAULT_TIMEOUT = 1e4;
167
173
  var SIGNAL_KEEPALIVE_INTERVAL = 5e3;
168
- var DISABLE_AUTH = true;
169
174
  var EdgeClient = class extends import_context.Resource {
170
175
  constructor(_identity, _config) {
171
176
  super();
@@ -183,6 +188,7 @@ var EdgeClient = class extends import_context.Resource {
183
188
  this._ws = void 0;
184
189
  this._keepaliveCtx = void 0;
185
190
  this._heartBeatContext = void 0;
191
+ this._baseUrl = getEdgeUrlWithProtocol(_config.socketEndpoint, "ws");
186
192
  }
187
193
  // TODO(burdon): Attach logging.
188
194
  get info() {
@@ -217,7 +223,7 @@ var EdgeClient = class extends import_context.Resource {
217
223
  info: this.info
218
224
  }, {
219
225
  F: __dxlog_file2,
220
- L: 119,
226
+ L: 122,
221
227
  S: this,
222
228
  C: (f, a) => f(...a)
223
229
  });
@@ -226,7 +232,7 @@ var EdgeClient = class extends import_context.Resource {
226
232
  err
227
233
  }, {
228
234
  F: __dxlog_file2,
229
- L: 121,
235
+ L: 124,
230
236
  S: this,
231
237
  C: (f, a) => f(...a)
232
238
  });
@@ -240,7 +246,7 @@ var EdgeClient = class extends import_context.Resource {
240
246
  peerKey: this._identity.peerKey
241
247
  }, {
242
248
  F: __dxlog_file2,
243
- L: 129,
249
+ L: 132,
244
250
  S: this,
245
251
  C: (f, a) => f(...a)
246
252
  });
@@ -248,20 +254,23 @@ var EdgeClient = class extends import_context.Resource {
248
254
  }
249
255
  async _openWebSocket() {
250
256
  let protocolHeader;
251
- if (!DISABLE_AUTH) {
257
+ if (!this._config.disableAuth) {
252
258
  const challenge = (0, import_crypto.randomBytes)(32);
253
259
  const credential = await this._identity.presentCredentials({
254
260
  challenge
255
261
  });
256
262
  protocolHeader = encodePresentationIntoAuthHeader(credential);
257
263
  }
258
- const url = new URL(`/ws/${this._identity.identityKey}/${this._identity.peerKey}`, this._config.socketEndpoint);
264
+ if (this._ctx.disposed) {
265
+ return;
266
+ }
267
+ const url = new URL(`/ws/${this._identity.identityKey}/${this._identity.peerKey}`, this._baseUrl);
259
268
  (0, import_log.log)("Opening websocket", {
260
269
  url: url.toString(),
261
270
  protocolHeader
262
271
  }, {
263
272
  F: __dxlog_file2,
264
- L: 144,
273
+ L: 151,
265
274
  S: this,
266
275
  C: (f, a) => f(...a)
267
276
  });
@@ -271,7 +280,7 @@ var EdgeClient = class extends import_context.Resource {
271
280
  this._ws.onopen = () => {
272
281
  (0, import_log.log)("opened", this.info, {
273
282
  F: __dxlog_file2,
274
- L: 148,
283
+ L: 155,
275
284
  S: this,
276
285
  C: (f, a) => f(...a)
277
286
  });
@@ -281,7 +290,7 @@ var EdgeClient = class extends import_context.Resource {
281
290
  this._ws.onclose = () => {
282
291
  (0, import_log.log)("closed", this.info, {
283
292
  F: __dxlog_file2,
284
- L: 153,
293
+ L: 160,
285
294
  S: this,
286
295
  C: (f, a) => f(...a)
287
296
  });
@@ -293,7 +302,7 @@ var EdgeClient = class extends import_context.Resource {
293
302
  info: event.message
294
303
  }, {
295
304
  F: __dxlog_file2,
296
- L: 157,
305
+ L: 164,
297
306
  S: this,
298
307
  C: (f, a) => f(...a)
299
308
  });
@@ -311,7 +320,7 @@ var EdgeClient = class extends import_context.Resource {
311
320
  payload: import_chunk_ANV2HBEH.protocol.getPayloadType(message)
312
321
  }, {
313
322
  F: __dxlog_file2,
314
- L: 170,
323
+ L: 177,
315
324
  S: this,
316
325
  C: (f, a) => f(...a)
317
326
  });
@@ -325,7 +334,7 @@ var EdgeClient = class extends import_context.Resource {
325
334
  payload: import_chunk_ANV2HBEH.protocol.getPayloadType(message)
326
335
  }, {
327
336
  F: __dxlog_file2,
328
- L: 176,
337
+ L: 183,
329
338
  S: this,
330
339
  C: (f, a) => f(...a)
331
340
  });
@@ -338,7 +347,7 @@ var EdgeClient = class extends import_context.Resource {
338
347
  });
339
348
  this._keepaliveCtx = new import_context.Context(void 0, {
340
349
  F: __dxlog_file2,
341
- L: 186
350
+ L: 193
342
351
  });
343
352
  (0, import_async.scheduleTaskInterval)(this._keepaliveCtx, async () => {
344
353
  this._ws?.send("__ping__");
@@ -373,7 +382,7 @@ var EdgeClient = class extends import_context.Resource {
373
382
  err
374
383
  }, {
375
384
  F: __dxlog_file2,
376
- L: 222,
385
+ L: 229,
377
386
  S: this,
378
387
  C: (f, a) => f(...a)
379
388
  });
@@ -387,7 +396,7 @@ var EdgeClient = class extends import_context.Resource {
387
396
  if (this._ready.state !== import_async.TriggerState.RESOLVED) {
388
397
  (0, import_log.log)("waiting for websocket to become ready", void 0, {
389
398
  F: __dxlog_file2,
390
- L: 232,
399
+ L: 239,
391
400
  S: this,
392
401
  C: (f, a) => f(...a)
393
402
  });
@@ -406,7 +415,7 @@ var EdgeClient = class extends import_context.Resource {
406
415
  payload: import_chunk_ANV2HBEH.protocol.getPayloadType(message)
407
416
  }, {
408
417
  F: __dxlog_file2,
409
- L: 245,
418
+ L: 252,
410
419
  S: this,
411
420
  C: (f, a) => f(...a)
412
421
  });
@@ -419,7 +428,7 @@ var EdgeClient = class extends import_context.Resource {
419
428
  void this._heartBeatContext?.dispose();
420
429
  this._heartBeatContext = new import_context.Context(void 0, {
421
430
  F: __dxlog_file2,
422
- L: 254
431
+ L: 261
423
432
  });
424
433
  (0, import_async.scheduleTask)(this._heartBeatContext, () => {
425
434
  this._persistentLifecycle.scheduleRestart();
@@ -532,14 +541,12 @@ var DEFAULT_RETRY_JITTER = 500;
532
541
  var DEFAULT_MAX_RETRIES_COUNT = 3;
533
542
  var EdgeHttpClient = class {
534
543
  constructor(baseUrl) {
535
- const url = new URL(baseUrl);
536
- url.protocol = "https";
537
- this._baseUrl = url.toString();
544
+ this._baseUrl = getEdgeUrlWithProtocol(baseUrl, "http");
538
545
  (0, import_log3.log)("created", {
539
546
  url: this._baseUrl
540
547
  }, {
541
548
  F: __dxlog_file3,
542
- L: 27,
549
+ L: 30,
543
550
  S: this,
544
551
  C: (f, a) => f(...a)
545
552
  });
@@ -557,10 +564,17 @@ var EdgeHttpClient = class {
557
564
  method: "POST"
558
565
  });
559
566
  }
567
+ async joinSpaceByInvitation(spaceId, body, args) {
568
+ return this._call(`/spaces/${spaceId}/join`, {
569
+ ...args,
570
+ body,
571
+ method: "POST"
572
+ });
573
+ }
560
574
  async _call(path, args) {
561
575
  const requestContext = args.context ?? new import_context3.Context(void 0, {
562
576
  F: __dxlog_file3,
563
- L: 43
577
+ L: 54
564
578
  });
565
579
  const shouldRetry = createRetryHandler(args);
566
580
  const request = createRequest(args);
@@ -570,7 +584,7 @@ var EdgeHttpClient = class {
570
584
  path
571
585
  }, {
572
586
  F: __dxlog_file3,
573
- L: 48,
587
+ L: 59,
574
588
  S: this,
575
589
  C: (f, a) => f(...a)
576
590
  });
@@ -585,27 +599,24 @@ var EdgeHttpClient = class {
585
599
  if (body.success) {
586
600
  return body.data;
587
601
  }
588
- const isNonRetryable = body.errorData != null;
589
- if (isNonRetryable) {
590
- throw new import_protocols.EdgeCallFailedError(body.reason, body.errorData);
602
+ if (body.errorData?.type === "auth_challenge" && typeof body.errorData?.challenge === "string") {
603
+ processingError = new import_protocols.EdgeAuthChallengeError(body.errorData.challenge, body.errorData);
604
+ } else {
605
+ processingError = import_protocols.EdgeCallFailedError.fromUnsuccessfulResponse(response, body);
591
606
  }
592
- processingError = new import_protocols.EdgeCallFailedError(body.reason);
593
607
  } else {
594
- processingError = import_protocols.EdgeCallFailedError.fromFailureResponse(response);
595
- if (!isRetryable(response.status)) {
596
- throw processingError;
597
- }
608
+ processingError = import_protocols.EdgeCallFailedError.fromHttpFailure(response);
598
609
  }
599
610
  } catch (error) {
600
611
  processingError = import_protocols.EdgeCallFailedError.fromProcessingFailureCause(error);
601
612
  }
602
- if (await shouldRetry(requestContext, retryAfterHeaderValue)) {
613
+ if (processingError.isRetryable && await shouldRetry(requestContext, retryAfterHeaderValue)) {
603
614
  import_log3.log.info("retrying edge request", {
604
615
  path,
605
616
  processingError
606
617
  }, {
607
618
  F: __dxlog_file3,
608
- L: 81,
619
+ L: 88,
609
620
  S: this,
610
621
  C: (f, a) => f(...a)
611
622
  });
@@ -621,12 +632,6 @@ var createRequest = (args) => {
621
632
  body: args.body && JSON.stringify(args.body)
622
633
  };
623
634
  };
624
- var isRetryable = (status) => {
625
- if (status === 501) {
626
- return false;
627
- }
628
- return !(status >= 400 && status < 500);
629
- };
630
635
  var createRetryHandler = (args) => {
631
636
  if (!args.retry || args.retry.count < 1) {
632
637
  return async () => false;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../../src/index.ts", "../../../src/edge-client.ts", "../../../src/errors.ts", "../../../src/persistent-lifecycle.ts", "../../../src/auth.ts", "../../../src/edge-http-client.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';\nexport * from './errors';\nexport * from './auth';\nexport * from './edge-http-client';\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 { randomBytes } from '@dxos/crypto';\nimport { log } from '@dxos/log';\nimport { buf } from '@dxos/protocols/buf';\nimport { type Message, MessageSchema } from '@dxos/protocols/buf/dxos/edge/messenger_pb';\nimport { schema } from '@dxos/protocols/proto';\nimport { type Presentation } from '@dxos/protocols/proto/dxos/halo/credentials';\n\nimport { protocol } from './defs';\nimport { EdgeConnectionClosedError, EdgeIdentityChangedError } 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 connected: Event;\n reconnect: Event;\n\n get info(): any;\n get identityKey(): string;\n get peerKey(): string;\n get isOpen(): boolean;\n get isConnected(): boolean;\n setIdentity(identity: EdgeIdentity): 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\nexport interface EdgeIdentity {\n peerKey: string;\n identityKey: string;\n /**\n * Returns credential presentation issued by the identity key.\n * Presentation must have the provided challenge.\n * Presentation may include ServiceAccess credentials.\n */\n presentCredentials({ challenge }: { challenge: Uint8Array }): Promise<Presentation>;\n}\n\nconst DISABLE_AUTH = true;\n\n/**\n * Messenger client.\n */\nexport class EdgeClient extends Resource implements EdgeConnection {\n public readonly reconnect = new Event();\n public readonly connected = 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 _ready = new Trigger();\n private _ws?: WebSocket = undefined;\n private _keepaliveCtx?: Context = undefined;\n private _heartBeatContext?: Context = undefined;\n\n constructor(\n private _identity: EdgeIdentity,\n private readonly _config: MessengerConfig,\n ) {\n super();\n }\n\n // TODO(burdon): Attach logging.\n public get info() {\n return {\n open: this.isOpen,\n identity: this._identity.identityKey,\n device: this._identity.peerKey,\n };\n }\n\n get isConnected() {\n return Boolean(this._ws) && this._ready.state === TriggerState.RESOLVED;\n }\n\n get identityKey() {\n return this._identity.identityKey;\n }\n\n get peerKey() {\n return this._identity.peerKey;\n }\n\n setIdentity(identity: EdgeIdentity) {\n this._identity = identity;\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._identity.peerKey });\n await this._persistentLifecycle.close();\n }\n\n private async _openWebSocket() {\n let protocolHeader: string | undefined;\n\n if (!DISABLE_AUTH) {\n // TODO(dmaretskyi): Get challenge from the WWW-Authenticate header returned by the endpoint.\n const challenge = randomBytes(32);\n const credential = await this._identity.presentCredentials({ challenge });\n protocolHeader = encodePresentationIntoAuthHeader(credential);\n }\n\n const url = new URL(`/ws/${this._identity.identityKey}/${this._identity.peerKey}`, this._config.socketEndpoint);\n log('Opening websocket', { url: url.toString(), protocolHeader });\n this._ws = new WebSocket(url, protocolHeader ? [protocolHeader] : []);\n\n this._ws.onopen = () => {\n log('opened', this.info);\n this._ready.wake();\n this.connected.emit();\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._identity.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 // TODO(dmaretskyi): Potential race condition here since web socket errors don't resolve this trigger.\n await this._ready.wait({ timeout: this._config.timeout ?? DEFAULT_TIMEOUT });\n\n // TODO(dmaretskyi): Potential leak: context re-assigned without disposing the previous one.\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(this.isOpen ? new EdgeIdentityChangedError() : new EdgeConnectionClosedError());\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 log('waiting for websocket to become ready');\n await this._ready.wait({ timeout: this._config.timeout ?? DEFAULT_TIMEOUT });\n }\n if (!this._ws) {\n throw new EdgeConnectionClosedError();\n }\n if (\n message.source &&\n (message.source.peerKey !== this._identity.peerKey || message.source.identityKey !== this.identityKey)\n ) {\n throw new EdgeIdentityChangedError();\n }\n\n log('sending...', { peerKey: this._identity.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\nconst encodePresentationIntoAuthHeader = (presentation: Presentation): string => {\n const encoded = schema.getCodecForType('dxos.halo.credentials.Presentation').encode(presentation);\n // = and / characters are not allowed in the WebSocket subprotocol header.\n const encodedToken = Buffer.from(encoded).toString('base64').replace(/=*$/, '').replaceAll('/', '|');\n\n return `base64url.bearer.authorization.dxos.org.${encodedToken}`;\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nexport class EdgeConnectionClosedError extends Error {\n constructor() {\n super('Edge connection closed.');\n }\n}\n\nexport class EdgeIdentityChangedError extends Error {\n constructor() {\n super('Edge identity changed.');\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", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { createCredential, signPresentation } from '@dxos/credentials';\nimport { type Signer } from '@dxos/crypto';\nimport { Keyring } from '@dxos/keyring';\nimport { PublicKey } from '@dxos/keys';\nimport { type Chain, type Credential } from '@dxos/protocols/proto/dxos/halo/credentials';\n\nimport type { EdgeIdentity } from './edge-client';\n\n/**\n * Edge identity backed by a device key without a credential chain.\n */\nexport const createDeviceEdgeIdentity = async (signer: Signer, key: PublicKey): Promise<EdgeIdentity> => {\n return {\n identityKey: key.toHex(),\n peerKey: key.toHex(),\n presentCredentials: async ({ challenge }) => {\n return signPresentation({\n presentation: {\n credentials: [\n // Verifier requires at least one credential in the presentation to establish the subject.\n await createCredential({\n assertion: {\n '@type': 'dxos.halo.credentials.Auth',\n },\n issuer: key,\n subject: key,\n signer,\n }),\n ],\n },\n signer,\n signerKey: key,\n nonce: challenge,\n });\n },\n };\n};\n\n/**\n * Edge identity backed by a chain of credentials.\n */\nexport const createChainEdgeIdentity = async (\n signer: Signer,\n identityKey: PublicKey,\n peerKey: PublicKey,\n chain: Chain,\n credentials: Credential[],\n): Promise<EdgeIdentity> => {\n const credentialsToSign =\n credentials.length > 0\n ? credentials\n : [\n await createCredential({\n assertion: {\n '@type': 'dxos.halo.credentials.Auth',\n },\n issuer: identityKey,\n subject: identityKey,\n signer,\n chain,\n signingKey: peerKey,\n }),\n ];\n\n return {\n identityKey: identityKey.toHex(),\n peerKey: peerKey.toHex(),\n presentCredentials: async ({ challenge }) => {\n return signPresentation({\n presentation: {\n credentials: credentialsToSign,\n },\n signer,\n nonce: challenge,\n signerKey: peerKey,\n chain,\n });\n },\n };\n};\n\n/**\n * Edge identity backed by a random ephemeral key without HALO.\n */\nexport const createEphemeralEdgeIdentity = async (): Promise<EdgeIdentity> => {\n const keyring = new Keyring();\n const key = await keyring.createKey();\n return createDeviceEdgeIdentity(keyring, key);\n};\n\n/**\n * Creates a HALO chain of credentials to act as an edge identity.\n */\nexport const createTestHaloEdgeIdentity = async (\n signer: Signer,\n identityKey: PublicKey,\n deviceKey: PublicKey,\n): Promise<EdgeIdentity> => {\n const deviceAdmission = await createCredential({\n assertion: {\n '@type': 'dxos.halo.credentials.AuthorizedDevice',\n deviceKey,\n identityKey,\n },\n issuer: identityKey,\n subject: deviceKey,\n signer,\n });\n return createChainEdgeIdentity(signer, identityKey, deviceKey, { credential: deviceAdmission }, [\n await createCredential({\n assertion: {\n '@type': 'dxos.halo.credentials.Auth',\n },\n issuer: identityKey,\n subject: identityKey,\n signer,\n }),\n ]);\n};\n\nexport const createStubEdgeIdentity = (): EdgeIdentity => {\n const identityKey = PublicKey.random();\n const deviceKey = PublicKey.random();\n return {\n identityKey: identityKey.toHex(),\n peerKey: deviceKey.toHex(),\n presentCredentials: async () => {\n throw new Error('Stub identity does not support authentication.');\n },\n };\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { sleep } from '@dxos/async';\nimport { Context } from '@dxos/context';\nimport { type SpaceId } from '@dxos/keys';\nimport { log } from '@dxos/log';\nimport {\n EdgeCallFailedError,\n type EdgeHttpResponse,\n type GetNotarizationResponseBody,\n type PostNotarizationRequestBody,\n} from '@dxos/protocols';\n\nconst DEFAULT_RETRY_TIMEOUT = 1500;\nconst DEFAULT_RETRY_JITTER = 500;\nconst DEFAULT_MAX_RETRIES_COUNT = 3;\n\nexport class EdgeHttpClient {\n private readonly _baseUrl: string;\n\n constructor(baseUrl: string) {\n const url = new URL(baseUrl);\n url.protocol = 'https';\n this._baseUrl = url.toString();\n log('created', { url: this._baseUrl });\n }\n\n public getCredentialsForNotarization(spaceId: SpaceId, args?: EdgeHttpGetArgs): Promise<GetNotarizationResponseBody> {\n return this._call(`/spaces/${spaceId}/notarization`, { ...args, method: 'GET' });\n }\n\n public async notarizeCredentials(\n spaceId: SpaceId,\n body: PostNotarizationRequestBody,\n args?: EdgeHttpGetArgs,\n ): Promise<void> {\n await this._call(`/spaces/${spaceId}/notarization`, { ...args, body, method: 'POST' });\n }\n\n private async _call<T>(path: string, args: EdgeHttpCallArgs): Promise<T> {\n const requestContext = args.context ?? new Context();\n const shouldRetry = createRetryHandler(args);\n const request = createRequest(args);\n const url = `${this._baseUrl}${path.startsWith('/') ? path.slice(1) : path}`;\n\n log.info('call', { method: args.method, path });\n\n while (true) {\n let processingError: EdgeCallFailedError;\n let retryAfterHeaderValue: number = Number.NaN;\n try {\n const response = await fetch(url, request);\n\n retryAfterHeaderValue = Number(response.headers.get('Retry-After'));\n\n if (response.ok) {\n const body = (await response.json()) as EdgeHttpResponse<T>;\n if (body.success) {\n return body.data;\n }\n\n const isNonRetryable = body.errorData != null;\n if (isNonRetryable) {\n throw new EdgeCallFailedError(body.reason, body.errorData);\n }\n\n processingError = new EdgeCallFailedError(body.reason);\n } else {\n processingError = EdgeCallFailedError.fromFailureResponse(response);\n if (!isRetryable(response.status)) {\n throw processingError;\n }\n }\n } catch (error: any) {\n processingError = EdgeCallFailedError.fromProcessingFailureCause(error);\n }\n\n if (await shouldRetry(requestContext, retryAfterHeaderValue)) {\n log.info('retrying edge request', { path, processingError });\n } else {\n throw processingError;\n }\n }\n }\n}\n\nconst createRequest = (args: EdgeHttpCallArgs): RequestInit => {\n return {\n method: args.method,\n body: args.body && JSON.stringify(args.body),\n };\n};\n\nconst isRetryable = (status: number) => {\n if (status === 501) {\n // Not Implemented\n return false;\n }\n // TODO: handle 401 Not Authorized\n return !(status >= 400 && status < 500);\n};\n\nconst createRetryHandler = (args: EdgeHttpCallArgs) => {\n if (!args.retry || args.retry.count < 1) {\n return async () => false;\n }\n let retries = 0;\n const maxRetries = args.retry.count ?? DEFAULT_MAX_RETRIES_COUNT;\n const baseTimeout = args.retry.timeout ?? DEFAULT_RETRY_TIMEOUT;\n const jitter = args.retry.jitter ?? DEFAULT_RETRY_JITTER;\n return async (ctx: Context, retryAfter: number) => {\n if (++retries > maxRetries || ctx.disposed) {\n return false;\n }\n\n if (retryAfter) {\n await sleep(retryAfter);\n } else {\n const timeout = baseTimeout + Math.random() * jitter;\n await sleep(timeout);\n }\n\n return true;\n };\n};\n\nexport type RetryConfig = {\n /**\n * A number of call retries, not counting the initial request.\n */\n count: number;\n /**\n * Delay before retries in ms.\n */\n timeout?: number;\n /**\n * A random amount of time before retrying to help prevent large bursts of requests.\n */\n jitter?: number;\n};\n\nexport type EdgeHttpGetArgs = { context?: Context; retry?: RetryConfig };\n\nexport type EdgeHttpPostArgs = { context?: Context; body?: any; retry?: RetryConfig };\n\ntype EdgeHttpCallArgs = {\n method: string;\n body?: any;\n context?: Context;\n retry?: RetryConfig;\n};\n"],
5
- "mappings": "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",
6
- "names": ["import_async", "import_context", "import_log", "EdgeConnectionClosedError", "Error", "constructor", "EdgeIdentityChangedError", "INIT_RESTART_DELAY", "DEFAULT_MAX_RESTART_DELAY", "PersistentLifecycle", "Resource", "start", "stop", "onRestart", "maxRestartDelay", "_restartTask", "undefined", "_restartAfter", "_start", "_stop", "_onRestart", "_maxRestartDelay", "_open", "DeferredTask", "_ctx", "_restart", "err", "log", "warn", "schedule", "catch", "_close", "join", "state", "_lifecycleState", "LifecycleState", "OPEN", "cancelWithContext", "sleep", "Math", "min", "max", "warnAfterTimeout", "scheduleRestart", "synchronized", "DEFAULT_TIMEOUT", "SIGNAL_KEEPALIVE_INTERVAL", "DISABLE_AUTH", "EdgeClient", "_identity", "_config", "reconnect", "Event", "connected", "_persistentLifecycle", "_openWebSocket", "_closeWebSocket", "emit", "_listeners", "Set", "_ready", "Trigger", "_ws", "_keepaliveCtx", "_heartBeatContext", "info", "open", "isOpen", "identity", "identityKey", "device", "peerKey", "isConnected", "Boolean", "TriggerState", "RESOLVED", "setIdentity", "addListener", "listener", "add", "delete", "close", "protocolHeader", "challenge", "randomBytes", "credential", "presentCredentials", "encodePresentationIntoAuthHeader", "url", "URL", "socketEndpoint", "toString", "WebSocket", "onopen", "wake", "onclose", "onerror", "event", "error", "message", "onmessage", "data", "_onHeartbeat", "toUint8Array", "buf", "fromBinary", "MessageSchema", "payload", "protocol", "getPayloadType", "wait", "timeout", "Context", "scheduleTaskInterval", "send", "throw", "reset", "dispose", "includes", "source", "toBinary", "scheduleTask", "presentation", "encoded", "schema", "getCodecForType", "encode", "encodedToken", "Buffer", "from", "replace", "replaceAll", "createDeviceEdgeIdentity", "signer", "key", "toHex", "signPresentation", "credentials", "createCredential", "assertion", "issuer", "subject", "signerKey", "nonce", "createChainEdgeIdentity", "chain", "credentialsToSign", "length", "signingKey", "createEphemeralEdgeIdentity", "keyring", "Keyring", "createKey", "createTestHaloEdgeIdentity", "deviceKey", "deviceAdmission", "createStubEdgeIdentity", "PublicKey", "random", "DEFAULT_RETRY_TIMEOUT", "DEFAULT_RETRY_JITTER", "DEFAULT_MAX_RETRIES_COUNT", "EdgeHttpClient", "baseUrl", "_baseUrl", "getCredentialsForNotarization", "spaceId", "args", "_call", "method", "notarizeCredentials", "body", "path", "requestContext", "context", "shouldRetry", "createRetryHandler", "request", "createRequest", "startsWith", "slice", "processingError", "retryAfterHeaderValue", "Number", "NaN", "response", "fetch", "headers", "get", "ok", "json", "success", "isNonRetryable", "errorData", "EdgeCallFailedError", "reason", "fromFailureResponse", "isRetryable", "status", "fromProcessingFailureCause", "JSON", "stringify", "retry", "count", "retries", "maxRetries", "baseTimeout", "jitter", "ctx", "retryAfter", "disposed"]
3
+ "sources": ["../../../src/index.ts", "../../../src/edge-client.ts", "../../../src/errors.ts", "../../../src/persistent-lifecycle.ts", "../../../src/utils.ts", "../../../src/auth.ts", "../../../src/edge-http-client.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';\nexport * from './errors';\nexport * from './auth';\nexport * from './edge-http-client';\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 { randomBytes } from '@dxos/crypto';\nimport { log } from '@dxos/log';\nimport { buf } from '@dxos/protocols/buf';\nimport { type Message, MessageSchema } from '@dxos/protocols/buf/dxos/edge/messenger_pb';\nimport { schema } from '@dxos/protocols/proto';\nimport { type Presentation } from '@dxos/protocols/proto/dxos/halo/credentials';\n\nimport { protocol } from './defs';\nimport { EdgeConnectionClosedError, EdgeIdentityChangedError } from './errors';\nimport { PersistentLifecycle } from './persistent-lifecycle';\nimport { type Protocol, toUint8Array } from './protocol';\nimport { getEdgeUrlWithProtocol } from './utils';\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 connected: Event;\n reconnect: Event;\n\n get info(): any;\n get identityKey(): string;\n get peerKey(): string;\n get isOpen(): boolean;\n get isConnected(): boolean;\n setIdentity(identity: EdgeIdentity): 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 disableAuth?: boolean;\n};\n\nexport interface EdgeIdentity {\n peerKey: string;\n identityKey: string;\n /**\n * Returns credential presentation issued by the identity key.\n * Presentation must have the provided challenge.\n * Presentation may include ServiceAccess credentials.\n */\n presentCredentials({ challenge }: { challenge: Uint8Array }): Promise<Presentation>;\n}\n\n/**\n * Messenger client.\n */\nexport class EdgeClient extends Resource implements EdgeConnection {\n public readonly reconnect = new Event();\n public readonly connected = 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 _ready = new Trigger();\n private _ws?: WebSocket = undefined;\n private _keepaliveCtx?: Context = undefined;\n private _heartBeatContext?: Context = undefined;\n\n private _baseUrl: string;\n\n constructor(\n private _identity: EdgeIdentity,\n private readonly _config: MessengerConfig,\n ) {\n super();\n this._baseUrl = getEdgeUrlWithProtocol(_config.socketEndpoint, 'ws');\n }\n\n // TODO(burdon): Attach logging.\n public get info() {\n return {\n open: this.isOpen,\n identity: this._identity.identityKey,\n device: this._identity.peerKey,\n };\n }\n\n get isConnected() {\n return Boolean(this._ws) && this._ready.state === TriggerState.RESOLVED;\n }\n\n get identityKey() {\n return this._identity.identityKey;\n }\n\n get peerKey() {\n return this._identity.peerKey;\n }\n\n setIdentity(identity: EdgeIdentity) {\n this._identity = identity;\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._identity.peerKey });\n await this._persistentLifecycle.close();\n }\n\n private async _openWebSocket() {\n let protocolHeader: string | undefined;\n\n if (!this._config.disableAuth) {\n // TODO(dmaretskyi): Get challenge from the WWW-Authenticate header returned by the endpoint.\n const challenge = randomBytes(32);\n const credential = await this._identity.presentCredentials({ challenge });\n protocolHeader = encodePresentationIntoAuthHeader(credential);\n }\n\n if (this._ctx.disposed) {\n return;\n }\n\n const url = new URL(`/ws/${this._identity.identityKey}/${this._identity.peerKey}`, this._baseUrl);\n log('Opening websocket', { url: url.toString(), protocolHeader });\n this._ws = new WebSocket(url, protocolHeader ? [protocolHeader] : []);\n\n this._ws.onopen = () => {\n log('opened', this.info);\n this._ready.wake();\n this.connected.emit();\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._identity.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 // TODO(dmaretskyi): Potential race condition here since web socket errors don't resolve this trigger.\n await this._ready.wait({ timeout: this._config.timeout ?? DEFAULT_TIMEOUT });\n\n // TODO(dmaretskyi): Potential leak: context re-assigned without disposing the previous one.\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(this.isOpen ? new EdgeIdentityChangedError() : new EdgeConnectionClosedError());\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 log('waiting for websocket to become ready');\n await this._ready.wait({ timeout: this._config.timeout ?? DEFAULT_TIMEOUT });\n }\n if (!this._ws) {\n throw new EdgeConnectionClosedError();\n }\n if (\n message.source &&\n (message.source.peerKey !== this._identity.peerKey || message.source.identityKey !== this.identityKey)\n ) {\n throw new EdgeIdentityChangedError();\n }\n\n log('sending...', { peerKey: this._identity.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\nconst encodePresentationIntoAuthHeader = (presentation: Presentation): string => {\n const encoded = schema.getCodecForType('dxos.halo.credentials.Presentation').encode(presentation);\n // = and / characters are not allowed in the WebSocket subprotocol header.\n const encodedToken = Buffer.from(encoded).toString('base64').replace(/=*$/, '').replaceAll('/', '|');\n\n return `base64url.bearer.authorization.dxos.org.${encodedToken}`;\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nexport class EdgeConnectionClosedError extends Error {\n constructor() {\n super('Edge connection closed.');\n }\n}\n\nexport class EdgeIdentityChangedError extends Error {\n constructor() {\n super('Edge identity changed.');\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", "//\n// Copyright 2024 DXOS.org\n//\n\nexport const getEdgeUrlWithProtocol = (baseUrl: string, protocol: 'http' | 'ws') => {\n const isSecure = baseUrl.startsWith('https') || baseUrl.startsWith('wss');\n const url = new URL(baseUrl);\n url.protocol = protocol + (isSecure ? 's' : '');\n return url.toString();\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { createCredential, signPresentation } from '@dxos/credentials';\nimport { type Signer } from '@dxos/crypto';\nimport { Keyring } from '@dxos/keyring';\nimport { PublicKey } from '@dxos/keys';\nimport { type Chain, type Credential } from '@dxos/protocols/proto/dxos/halo/credentials';\n\nimport type { EdgeIdentity } from './edge-client';\n\n/**\n * Edge identity backed by a device key without a credential chain.\n */\nexport const createDeviceEdgeIdentity = async (signer: Signer, key: PublicKey): Promise<EdgeIdentity> => {\n return {\n identityKey: key.toHex(),\n peerKey: key.toHex(),\n presentCredentials: async ({ challenge }) => {\n return signPresentation({\n presentation: {\n credentials: [\n // Verifier requires at least one credential in the presentation to establish the subject.\n await createCredential({\n assertion: {\n '@type': 'dxos.halo.credentials.Auth',\n },\n issuer: key,\n subject: key,\n signer,\n }),\n ],\n },\n signer,\n signerKey: key,\n nonce: challenge,\n });\n },\n };\n};\n\n/**\n * Edge identity backed by a chain of credentials.\n */\nexport const createChainEdgeIdentity = async (\n signer: Signer,\n identityKey: PublicKey,\n peerKey: PublicKey,\n chain: Chain,\n credentials: Credential[],\n): Promise<EdgeIdentity> => {\n const credentialsToSign =\n credentials.length > 0\n ? credentials\n : [\n await createCredential({\n assertion: {\n '@type': 'dxos.halo.credentials.Auth',\n },\n issuer: identityKey,\n subject: identityKey,\n signer,\n chain,\n signingKey: peerKey,\n }),\n ];\n\n return {\n identityKey: identityKey.toHex(),\n peerKey: peerKey.toHex(),\n presentCredentials: async ({ challenge }) => {\n return signPresentation({\n presentation: {\n credentials: credentialsToSign,\n },\n signer,\n nonce: challenge,\n signerKey: peerKey,\n chain,\n });\n },\n };\n};\n\n/**\n * Edge identity backed by a random ephemeral key without HALO.\n */\nexport const createEphemeralEdgeIdentity = async (): Promise<EdgeIdentity> => {\n const keyring = new Keyring();\n const key = await keyring.createKey();\n return createDeviceEdgeIdentity(keyring, key);\n};\n\n/**\n * Creates a HALO chain of credentials to act as an edge identity.\n */\nexport const createTestHaloEdgeIdentity = async (\n signer: Signer,\n identityKey: PublicKey,\n deviceKey: PublicKey,\n): Promise<EdgeIdentity> => {\n const deviceAdmission = await createCredential({\n assertion: {\n '@type': 'dxos.halo.credentials.AuthorizedDevice',\n deviceKey,\n identityKey,\n },\n issuer: identityKey,\n subject: deviceKey,\n signer,\n });\n return createChainEdgeIdentity(signer, identityKey, deviceKey, { credential: deviceAdmission }, [\n await createCredential({\n assertion: {\n '@type': 'dxos.halo.credentials.Auth',\n },\n issuer: identityKey,\n subject: identityKey,\n signer,\n }),\n ]);\n};\n\nexport const createStubEdgeIdentity = (): EdgeIdentity => {\n const identityKey = PublicKey.random();\n const deviceKey = PublicKey.random();\n return {\n identityKey: identityKey.toHex(),\n peerKey: deviceKey.toHex(),\n presentCredentials: async () => {\n throw new Error('Stub identity does not support authentication.');\n },\n };\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { sleep } from '@dxos/async';\nimport { Context } from '@dxos/context';\nimport { type SpaceId } from '@dxos/keys';\nimport { log } from '@dxos/log';\nimport {\n EdgeCallFailedError,\n type EdgeHttpResponse,\n type GetNotarizationResponseBody,\n type PostNotarizationRequestBody,\n type JoinSpaceRequest,\n type JoinSpaceResponseBody,\n EdgeAuthChallengeError,\n} from '@dxos/protocols';\n\nimport { getEdgeUrlWithProtocol } from './utils';\n\nconst DEFAULT_RETRY_TIMEOUT = 1500;\nconst DEFAULT_RETRY_JITTER = 500;\nconst DEFAULT_MAX_RETRIES_COUNT = 3;\n\nexport class EdgeHttpClient {\n private readonly _baseUrl: string;\n\n constructor(baseUrl: string) {\n this._baseUrl = getEdgeUrlWithProtocol(baseUrl, 'http');\n log('created', { url: this._baseUrl });\n }\n\n public getCredentialsForNotarization(spaceId: SpaceId, args?: EdgeHttpGetArgs): Promise<GetNotarizationResponseBody> {\n return this._call(`/spaces/${spaceId}/notarization`, { ...args, method: 'GET' });\n }\n\n public async notarizeCredentials(\n spaceId: SpaceId,\n body: PostNotarizationRequestBody,\n args?: EdgeHttpGetArgs,\n ): Promise<void> {\n await this._call(`/spaces/${spaceId}/notarization`, { ...args, body, method: 'POST' });\n }\n\n public async joinSpaceByInvitation(\n spaceId: SpaceId,\n body: JoinSpaceRequest,\n args?: EdgeHttpGetArgs,\n ): Promise<JoinSpaceResponseBody> {\n return this._call(`/spaces/${spaceId}/join`, { ...args, body, method: 'POST' });\n }\n\n private async _call<T>(path: string, args: EdgeHttpCallArgs): Promise<T> {\n const requestContext = args.context ?? new Context();\n const shouldRetry = createRetryHandler(args);\n const request = createRequest(args);\n const url = `${this._baseUrl}${path.startsWith('/') ? path.slice(1) : path}`;\n\n log.info('call', { method: args.method, path });\n\n while (true) {\n let processingError: EdgeCallFailedError;\n let retryAfterHeaderValue: number = Number.NaN;\n try {\n const response = await fetch(url, request);\n\n retryAfterHeaderValue = Number(response.headers.get('Retry-After'));\n\n if (response.ok) {\n const body = (await response.json()) as EdgeHttpResponse<T>;\n if (body.success) {\n return body.data;\n }\n\n if (body.errorData?.type === 'auth_challenge' && typeof body.errorData?.challenge === 'string') {\n processingError = new EdgeAuthChallengeError(body.errorData.challenge, body.errorData);\n } else {\n processingError = EdgeCallFailedError.fromUnsuccessfulResponse(response, body);\n }\n } else {\n processingError = EdgeCallFailedError.fromHttpFailure(response);\n }\n } catch (error: any) {\n processingError = EdgeCallFailedError.fromProcessingFailureCause(error);\n }\n\n if (processingError.isRetryable && (await shouldRetry(requestContext, retryAfterHeaderValue))) {\n log.info('retrying edge request', { path, processingError });\n } else {\n throw processingError;\n }\n }\n }\n}\n\nconst createRequest = (args: EdgeHttpCallArgs): RequestInit => {\n return {\n method: args.method,\n body: args.body && JSON.stringify(args.body),\n };\n};\n\nconst createRetryHandler = (args: EdgeHttpCallArgs) => {\n if (!args.retry || args.retry.count < 1) {\n return async () => false;\n }\n let retries = 0;\n const maxRetries = args.retry.count ?? DEFAULT_MAX_RETRIES_COUNT;\n const baseTimeout = args.retry.timeout ?? DEFAULT_RETRY_TIMEOUT;\n const jitter = args.retry.jitter ?? DEFAULT_RETRY_JITTER;\n return async (ctx: Context, retryAfter: number) => {\n if (++retries > maxRetries || ctx.disposed) {\n return false;\n }\n\n if (retryAfter) {\n await sleep(retryAfter);\n } else {\n const timeout = baseTimeout + Math.random() * jitter;\n await sleep(timeout);\n }\n\n return true;\n };\n};\n\nexport type RetryConfig = {\n /**\n * A number of call retries, not counting the initial request.\n */\n count: number;\n /**\n * Delay before retries in ms.\n */\n timeout?: number;\n /**\n * A random amount of time before retrying to help prevent large bursts of requests.\n */\n jitter?: number;\n};\n\nexport type EdgeHttpGetArgs = { context?: Context; retry?: RetryConfig };\n\nexport type EdgeHttpPostArgs = { context?: Context; body?: any; retry?: RetryConfig };\n\ntype EdgeHttpCallArgs = {\n method: string;\n body?: any;\n context?: Context;\n retry?: RetryConfig;\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["import_async", "import_context", "import_log", "EdgeConnectionClosedError", "Error", "constructor", "EdgeIdentityChangedError", "INIT_RESTART_DELAY", "DEFAULT_MAX_RESTART_DELAY", "PersistentLifecycle", "Resource", "start", "stop", "onRestart", "maxRestartDelay", "_restartTask", "undefined", "_restartAfter", "_start", "_stop", "_onRestart", "_maxRestartDelay", "_open", "DeferredTask", "_ctx", "_restart", "err", "log", "warn", "schedule", "catch", "_close", "join", "state", "_lifecycleState", "LifecycleState", "OPEN", "cancelWithContext", "sleep", "Math", "min", "max", "warnAfterTimeout", "scheduleRestart", "synchronized", "getEdgeUrlWithProtocol", "baseUrl", "protocol", "isSecure", "startsWith", "url", "URL", "toString", "DEFAULT_TIMEOUT", "SIGNAL_KEEPALIVE_INTERVAL", "EdgeClient", "_identity", "_config", "reconnect", "Event", "connected", "_persistentLifecycle", "_openWebSocket", "_closeWebSocket", "emit", "_listeners", "Set", "_ready", "Trigger", "_ws", "_keepaliveCtx", "_heartBeatContext", "_baseUrl", "socketEndpoint", "info", "open", "isOpen", "identity", "identityKey", "device", "peerKey", "isConnected", "Boolean", "TriggerState", "RESOLVED", "setIdentity", "addListener", "listener", "add", "delete", "close", "protocolHeader", "disableAuth", "challenge", "randomBytes", "credential", "presentCredentials", "encodePresentationIntoAuthHeader", "disposed", "WebSocket", "onopen", "wake", "onclose", "onerror", "event", "error", "message", "onmessage", "data", "_onHeartbeat", "toUint8Array", "buf", "fromBinary", "MessageSchema", "payload", "getPayloadType", "wait", "timeout", "Context", "scheduleTaskInterval", "send", "throw", "reset", "dispose", "includes", "source", "toBinary", "scheduleTask", "presentation", "encoded", "schema", "getCodecForType", "encode", "encodedToken", "Buffer", "from", "replace", "replaceAll", "createDeviceEdgeIdentity", "signer", "key", "toHex", "signPresentation", "credentials", "createCredential", "assertion", "issuer", "subject", "signerKey", "nonce", "createChainEdgeIdentity", "chain", "credentialsToSign", "length", "signingKey", "createEphemeralEdgeIdentity", "keyring", "Keyring", "createKey", "createTestHaloEdgeIdentity", "deviceKey", "deviceAdmission", "createStubEdgeIdentity", "PublicKey", "random", "DEFAULT_RETRY_TIMEOUT", "DEFAULT_RETRY_JITTER", "DEFAULT_MAX_RETRIES_COUNT", "EdgeHttpClient", "getCredentialsForNotarization", "spaceId", "args", "_call", "method", "notarizeCredentials", "body", "joinSpaceByInvitation", "path", "requestContext", "context", "shouldRetry", "createRetryHandler", "request", "createRequest", "slice", "processingError", "retryAfterHeaderValue", "Number", "NaN", "response", "fetch", "headers", "get", "ok", "json", "success", "errorData", "type", "EdgeAuthChallengeError", "EdgeCallFailedError", "fromUnsuccessfulResponse", "fromHttpFailure", "fromProcessingFailureCause", "isRetryable", "JSON", "stringify", "retry", "count", "retries", "maxRetries", "baseTimeout", "jitter", "ctx", "retryAfter"]
7
7
  }
@@ -1 +1 @@
1
- {"inputs":{"packages/core/mesh/edge-client/src/protocol.ts":{"bytes":10334,"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":1607,"imports":[{"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/protocol.ts","kind":"import-statement","original":"./protocol"}],"format":"esm"},"packages/core/mesh/edge-client/src/errors.ts":{"bytes":1265,"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":32385,"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/crypto","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":"@dxos/protocols/proto","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/auth.ts":{"bytes":11621,"imports":[{"path":"@dxos/credentials","kind":"import-statement","external":true},{"path":"@dxos/keyring","kind":"import-statement","external":true},{"path":"@dxos/keys","kind":"import-statement","external":true}],"format":"esm"},"packages/core/mesh/edge-client/src/edge-http-client.ts":{"bytes":15155,"imports":[{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/protocols","kind":"import-statement","external":true}],"format":"esm"},"packages/core/mesh/edge-client/src/index.ts":{"bytes":1127,"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"},{"path":"packages/core/mesh/edge-client/src/errors.ts","kind":"import-statement","original":"./errors"},{"path":"packages/core/mesh/edge-client/src/auth.ts","kind":"import-statement","original":"./auth"},{"path":"packages/core/mesh/edge-client/src/edge-http-client.ts","kind":"import-statement","original":"./edge-http-client"}],"format":"esm"},"packages/core/mesh/edge-client/src/testing/test-utils.ts":{"bytes":12455,"imports":[{"path":"isomorphic-ws","kind":"import-statement","external":true},{"path":"@dxos/async","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/testing/index.ts":{"bytes":516,"imports":[{"path":"packages/core/mesh/edge-client/src/testing/test-utils.ts","kind":"import-statement","original":"./test-utils"}],"format":"esm"}},"outputs":{"packages/core/mesh/edge-client/dist/lib/node/index.cjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":34449},"packages/core/mesh/edge-client/dist/lib/node/index.cjs":{"imports":[{"path":"packages/core/mesh/edge-client/dist/lib/node/chunk-ANV2HBEH.cjs","kind":"import-statement"},{"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/crypto","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":"@dxos/protocols/proto","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},{"path":"@dxos/credentials","kind":"import-statement","external":true},{"path":"@dxos/keyring","kind":"import-statement","external":true},{"path":"@dxos/keys","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/protocols","kind":"import-statement","external":true}],"exports":["EdgeClient","EdgeConnectionClosedError","EdgeHttpClient","EdgeIdentityChangedError","Protocol","createChainEdgeIdentity","createDeviceEdgeIdentity","createEphemeralEdgeIdentity","createStubEdgeIdentity","createTestHaloEdgeIdentity","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":7977},"packages/core/mesh/edge-client/src/errors.ts":{"bytesInOutput":232},"packages/core/mesh/edge-client/src/persistent-lifecycle.ts":{"bytesInOutput":3015},"packages/core/mesh/edge-client/src/auth.ts":{"bytesInOutput":2681},"packages/core/mesh/edge-client/src/edge-http-client.ts":{"bytesInOutput":3649}},"bytes":18414},"packages/core/mesh/edge-client/dist/lib/node/testing/index.cjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":6341},"packages/core/mesh/edge-client/dist/lib/node/testing/index.cjs":{"imports":[{"path":"packages/core/mesh/edge-client/dist/lib/node/chunk-ANV2HBEH.cjs","kind":"import-statement"},{"path":"isomorphic-ws","kind":"import-statement","external":true},{"path":"@dxos/async","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}],"exports":["DEFAULT_PORT","createTestEdgeWsServer"],"entryPoint":"packages/core/mesh/edge-client/src/testing/index.ts","inputs":{"packages/core/mesh/edge-client/src/testing/test-utils.ts":{"bytesInOutput":3276},"packages/core/mesh/edge-client/src/testing/index.ts":{"bytesInOutput":0}},"bytes":3493},"packages/core/mesh/edge-client/dist/lib/node/chunk-ANV2HBEH.cjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":5676},"packages/core/mesh/edge-client/dist/lib/node/chunk-ANV2HBEH.cjs":{"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},{"path":"@dxos/protocols/buf","kind":"import-statement","external":true},{"path":"@dxos/protocols/buf/dxos/edge/messenger_pb","kind":"import-statement","external":true}],"exports":["Protocol","getTypename","protocol","toUint8Array"],"inputs":{"packages/core/mesh/edge-client/src/protocol.ts":{"bytesInOutput":2600},"packages/core/mesh/edge-client/src/defs.ts":{"bytesInOutput":298}},"bytes":3106}}}
1
+ {"inputs":{"packages/core/mesh/edge-client/src/protocol.ts":{"bytes":10334,"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":1607,"imports":[{"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/protocol.ts","kind":"import-statement","original":"./protocol"}],"format":"esm"},"packages/core/mesh/edge-client/src/errors.ts":{"bytes":1265,"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/utils.ts":{"bytes":1451,"imports":[],"format":"esm"},"packages/core/mesh/edge-client/src/edge-client.ts":{"bytes":33114,"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/crypto","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":"@dxos/protocols/proto","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"},{"path":"packages/core/mesh/edge-client/src/utils.ts","kind":"import-statement","original":"./utils"}],"format":"esm"},"packages/core/mesh/edge-client/src/auth.ts":{"bytes":11621,"imports":[{"path":"@dxos/credentials","kind":"import-statement","external":true},{"path":"@dxos/keyring","kind":"import-statement","external":true},{"path":"@dxos/keys","kind":"import-statement","external":true}],"format":"esm"},"packages/core/mesh/edge-client/src/edge-http-client.ts":{"bytes":15505,"imports":[{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/protocols","kind":"import-statement","external":true},{"path":"packages/core/mesh/edge-client/src/utils.ts","kind":"import-statement","original":"./utils"}],"format":"esm"},"packages/core/mesh/edge-client/src/index.ts":{"bytes":1127,"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"},{"path":"packages/core/mesh/edge-client/src/errors.ts","kind":"import-statement","original":"./errors"},{"path":"packages/core/mesh/edge-client/src/auth.ts","kind":"import-statement","original":"./auth"},{"path":"packages/core/mesh/edge-client/src/edge-http-client.ts","kind":"import-statement","original":"./edge-http-client"}],"format":"esm"},"packages/core/mesh/edge-client/src/testing/test-utils.ts":{"bytes":12827,"imports":[{"path":"isomorphic-ws","kind":"import-statement","external":true},{"path":"@dxos/async","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/testing/index.ts":{"bytes":516,"imports":[{"path":"packages/core/mesh/edge-client/src/testing/test-utils.ts","kind":"import-statement","original":"./test-utils"}],"format":"esm"}},"outputs":{"packages/core/mesh/edge-client/dist/lib/node/index.cjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":35687},"packages/core/mesh/edge-client/dist/lib/node/index.cjs":{"imports":[{"path":"packages/core/mesh/edge-client/dist/lib/node/chunk-ANV2HBEH.cjs","kind":"import-statement"},{"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/crypto","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":"@dxos/protocols/proto","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},{"path":"@dxos/credentials","kind":"import-statement","external":true},{"path":"@dxos/keyring","kind":"import-statement","external":true},{"path":"@dxos/keys","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/protocols","kind":"import-statement","external":true}],"exports":["EdgeClient","EdgeConnectionClosedError","EdgeHttpClient","EdgeIdentityChangedError","Protocol","createChainEdgeIdentity","createDeviceEdgeIdentity","createEphemeralEdgeIdentity","createStubEdgeIdentity","createTestHaloEdgeIdentity","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":8074},"packages/core/mesh/edge-client/src/errors.ts":{"bytesInOutput":232},"packages/core/mesh/edge-client/src/persistent-lifecycle.ts":{"bytesInOutput":3015},"packages/core/mesh/edge-client/src/utils.ts":{"bytesInOutput":244},"packages/core/mesh/edge-client/src/auth.ts":{"bytesInOutput":2681},"packages/core/mesh/edge-client/src/edge-http-client.ts":{"bytesInOutput":3701}},"bytes":18855},"packages/core/mesh/edge-client/dist/lib/node/testing/index.cjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":6549},"packages/core/mesh/edge-client/dist/lib/node/testing/index.cjs":{"imports":[{"path":"packages/core/mesh/edge-client/dist/lib/node/chunk-ANV2HBEH.cjs","kind":"import-statement"},{"path":"isomorphic-ws","kind":"import-statement","external":true},{"path":"@dxos/async","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}],"exports":["DEFAULT_PORT","createTestEdgeWsServer"],"entryPoint":"packages/core/mesh/edge-client/src/testing/index.ts","inputs":{"packages/core/mesh/edge-client/src/testing/test-utils.ts":{"bytesInOutput":3368},"packages/core/mesh/edge-client/src/testing/index.ts":{"bytesInOutput":0}},"bytes":3585},"packages/core/mesh/edge-client/dist/lib/node/chunk-ANV2HBEH.cjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":5676},"packages/core/mesh/edge-client/dist/lib/node/chunk-ANV2HBEH.cjs":{"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},{"path":"@dxos/protocols/buf","kind":"import-statement","external":true},{"path":"@dxos/protocols/buf/dxos/edge/messenger_pb","kind":"import-statement","external":true}],"exports":["Protocol","getTypename","protocol","toUint8Array"],"inputs":{"packages/core/mesh/edge-client/src/protocol.ts":{"bytesInOutput":2600},"packages/core/mesh/edge-client/src/defs.ts":{"bytesInOutput":298}},"bytes":3106}}}
@@ -91,6 +91,9 @@ var createTestEdgeWsServer = async (port = DEFAULT_PORT, params) => {
91
91
  cleanup: () => server.close(),
92
92
  currentConnection: () => connection,
93
93
  sendResponseMessage,
94
+ sendMessage: (msg) => {
95
+ connection.send(import_buf.buf.toBinary(import_messenger_pb.MessageSchema, msg));
96
+ },
94
97
  closeConnection: () => {
95
98
  closeTrigger.reset();
96
99
  connection.close(1011);
@@ -103,7 +106,7 @@ var createConnectionDelayHandler = (params) => {
103
106
  if (params?.admitConnection) {
104
107
  (0, import_log.log)("delaying edge connection admission", void 0, {
105
108
  F: __dxlog_file,
106
- L: 75,
109
+ L: 78,
107
110
  S: void 0,
108
111
  C: (f, a) => f(...a)
109
112
  });
@@ -111,7 +114,7 @@ var createConnectionDelayHandler = (params) => {
111
114
  callback(true);
112
115
  (0, import_log.log)("edge connection admitted", void 0, {
113
116
  F: __dxlog_file,
114
- L: 78,
117
+ L: 81,
115
118
  S: void 0,
116
119
  C: (f, a) => f(...a)
117
120
  });
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/testing/test-utils.ts"],
4
- "sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport WebSocket from 'isomorphic-ws';\n\nimport { Trigger } from '@dxos/async';\nimport { log } from '@dxos/log';\nimport { buf } from '@dxos/protocols/buf';\nimport { MessageSchema, TextMessageSchema, type Message } from '@dxos/protocols/buf/dxos/edge/messenger_pb';\n\nimport { protocol } from '../defs';\nimport { toUint8Array } from '../protocol';\n\nexport const DEFAULT_PORT = 8080;\n\ntype TestEdgeWsServerParams = {\n admitConnection?: Trigger;\n payloadDecoder?: (payload: Uint8Array) => any;\n messageHandler?: (payload: any) => Promise<Uint8Array | undefined>;\n};\n\nexport const createTestEdgeWsServer = async (port = DEFAULT_PORT, params?: TestEdgeWsServerParams) => {\n const server = new WebSocket.Server({ port, verifyClient: createConnectionDelayHandler(params) });\n\n let connection: WebSocket | undefined;\n\n const messageSink: any[] = [];\n const closeTrigger = new Trigger();\n const sendResponseMessage = createResponseSender(() => connection!);\n\n server.on('connection', (ws) => {\n connection = ws;\n ws.on('error', (err) => log.catch(err));\n ws.on('message', async (data) => {\n if (String(data) === '__ping__') {\n ws.send('__pong__');\n return;\n }\n const { request, requestPayload } = await decodeRequest(params, data);\n if (params?.messageHandler) {\n const responsePayload = await params.messageHandler(requestPayload);\n if (responsePayload && connection) {\n sendResponseMessage(request, responsePayload);\n }\n }\n log('message', { payload: requestPayload });\n messageSink.push(requestPayload);\n });\n\n ws.on('close', () => {\n connection = undefined;\n closeTrigger.wake();\n });\n });\n\n return {\n server,\n messageSink,\n endpoint: `ws://localhost:${port}`,\n cleanup: () => server.close(),\n currentConnection: () => connection,\n sendResponseMessage,\n closeConnection: () => {\n closeTrigger.reset();\n connection!.close(1011);\n return closeTrigger.wait();\n },\n };\n};\n\nconst createConnectionDelayHandler = (params: TestEdgeWsServerParams | undefined) => {\n return (_: any, callback: (admit: boolean) => void) => {\n if (params?.admitConnection) {\n log('delaying edge connection admission');\n void params.admitConnection.wait().then(() => {\n callback(true);\n log('edge connection admitted');\n });\n } else {\n callback(true);\n }\n };\n};\n\nconst createResponseSender = (connection: () => WebSocket) => {\n return (request: Message, responsePayload: Uint8Array) => {\n const recipient = request.source!;\n connection().send(\n buf.toBinary(\n MessageSchema,\n buf.create(MessageSchema, {\n source: {\n identityKey: recipient.identityKey,\n peerKey: recipient.peerKey,\n },\n serviceId: request.serviceId!,\n payload: { value: responsePayload },\n }),\n ),\n );\n };\n};\n\nconst decodeRequest = async (params: TestEdgeWsServerParams | undefined, data: any) => {\n const request = buf.fromBinary(MessageSchema, await toUint8Array(data));\n const requestPayload = params?.payloadDecoder\n ? params.payloadDecoder(request.payload!.value!)\n : protocol.getPayload(request, TextMessageSchema);\n return { request, requestPayload };\n};\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,2BAAsB;AAEtB,mBAAwB;AACxB,iBAAoB;AACpB,iBAAoB;AACpB,0BAA+D;;AAKxD,IAAMA,eAAe;AAQrB,IAAMC,yBAAyB,OAAOC,OAAOF,cAAcG,WAAAA;AAChE,QAAMC,SAAS,IAAIC,qBAAAA,QAAUC,OAAO;IAAEJ;IAAMK,cAAcC,6BAA6BL,MAAAA;EAAQ,CAAA;AAE/F,MAAIM;AAEJ,QAAMC,cAAqB,CAAA;AAC3B,QAAMC,eAAe,IAAIC,qBAAAA;AACzB,QAAMC,sBAAsBC,qBAAqB,MAAML,UAAAA;AAEvDL,SAAOW,GAAG,cAAc,CAACC,OAAAA;AACvBP,iBAAaO;AACbA,OAAGD,GAAG,SAAS,CAACE,QAAQC,eAAIC,MAAMF,KAAAA,QAAAA;;;;;;AAClCD,OAAGD,GAAG,WAAW,OAAOK,SAAAA;AACtB,UAAIC,OAAOD,IAAAA,MAAU,YAAY;AAC/BJ,WAAGM,KAAK,UAAA;AACR;MACF;AACA,YAAM,EAAEC,SAASC,eAAc,IAAK,MAAMC,cAActB,QAAQiB,IAAAA;AAChE,UAAIjB,QAAQuB,gBAAgB;AAC1B,cAAMC,kBAAkB,MAAMxB,OAAOuB,eAAeF,cAAAA;AACpD,YAAIG,mBAAmBlB,YAAY;AACjCI,8BAAoBU,SAASI,eAAAA;QAC/B;MACF;AACAT,0BAAI,WAAW;QAAEU,SAASJ;MAAe,GAAA;;;;;;AACzCd,kBAAYmB,KAAKL,cAAAA;IACnB,CAAA;AAEAR,OAAGD,GAAG,SAAS,MAAA;AACbN,mBAAaqB;AACbnB,mBAAaoB,KAAI;IACnB,CAAA;EACF,CAAA;AAEA,SAAO;IACL3B;IACAM;IACAsB,UAAU,kBAAkB9B,IAAAA;IAC5B+B,SAAS,MAAM7B,OAAO8B,MAAK;IAC3BC,mBAAmB,MAAM1B;IACzBI;IACAuB,iBAAiB,MAAA;AACfzB,mBAAa0B,MAAK;AAClB5B,iBAAYyB,MAAM,IAAA;AAClB,aAAOvB,aAAa2B,KAAI;IAC1B;EACF;AACF;AAEA,IAAM9B,+BAA+B,CAACL,WAAAA;AACpC,SAAO,CAACoC,GAAQC,aAAAA;AACd,QAAIrC,QAAQsC,iBAAiB;AAC3BvB,0BAAI,sCAAA,QAAA;;;;;;AACJ,WAAKf,OAAOsC,gBAAgBH,KAAI,EAAGI,KAAK,MAAA;AACtCF,iBAAS,IAAA;AACTtB,4BAAI,4BAAA,QAAA;;;;;;MACN,CAAA;IACF,OAAO;AACLsB,eAAS,IAAA;IACX;EACF;AACF;AAEA,IAAM1B,uBAAuB,CAACL,eAAAA;AAC5B,SAAO,CAACc,SAAkBI,oBAAAA;AACxB,UAAMgB,YAAYpB,QAAQqB;AAC1BnC,eAAAA,EAAaa,KACXuB,eAAIC,SACFC,mCACAF,eAAIG,OAAOD,mCAAe;MACxBH,QAAQ;QACNK,aAAaN,UAAUM;QACvBC,SAASP,UAAUO;MACrB;MACAC,WAAW5B,QAAQ4B;MACnBvB,SAAS;QAAEwB,OAAOzB;MAAgB;IACpC,CAAA,CAAA,CAAA;EAGN;AACF;AAEA,IAAMF,gBAAgB,OAAOtB,QAA4CiB,SAAAA;AACvE,QAAMG,UAAUsB,eAAIQ,WAAWN,mCAAe,UAAMO,oCAAalC,IAAAA,CAAAA;AACjE,QAAMI,iBAAiBrB,QAAQoD,iBAC3BpD,OAAOoD,eAAehC,QAAQK,QAASwB,KAAK,IAC5CI,+BAASC,WAAWlC,SAASmC,qCAAAA;AACjC,SAAO;IAAEnC;IAASC;EAAe;AACnC;",
6
- "names": ["DEFAULT_PORT", "createTestEdgeWsServer", "port", "params", "server", "WebSocket", "Server", "verifyClient", "createConnectionDelayHandler", "connection", "messageSink", "closeTrigger", "Trigger", "sendResponseMessage", "createResponseSender", "on", "ws", "err", "log", "catch", "data", "String", "send", "request", "requestPayload", "decodeRequest", "messageHandler", "responsePayload", "payload", "push", "undefined", "wake", "endpoint", "cleanup", "close", "currentConnection", "closeConnection", "reset", "wait", "_", "callback", "admitConnection", "then", "recipient", "source", "buf", "toBinary", "MessageSchema", "create", "identityKey", "peerKey", "serviceId", "value", "fromBinary", "toUint8Array", "payloadDecoder", "protocol", "getPayload", "TextMessageSchema"]
4
+ "sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport WebSocket from 'isomorphic-ws';\n\nimport { Trigger } from '@dxos/async';\nimport { log } from '@dxos/log';\nimport { buf } from '@dxos/protocols/buf';\nimport { MessageSchema, TextMessageSchema, type Message } from '@dxos/protocols/buf/dxos/edge/messenger_pb';\n\nimport { protocol } from '../defs';\nimport { toUint8Array } from '../protocol';\n\nexport const DEFAULT_PORT = 8080;\n\ntype TestEdgeWsServerParams = {\n admitConnection?: Trigger;\n payloadDecoder?: (payload: Uint8Array) => any;\n messageHandler?: (payload: any) => Promise<Uint8Array | undefined>;\n};\n\nexport const createTestEdgeWsServer = async (port = DEFAULT_PORT, params?: TestEdgeWsServerParams) => {\n const server = new WebSocket.Server({ port, verifyClient: createConnectionDelayHandler(params) });\n\n let connection: WebSocket | undefined;\n\n const messageSink: any[] = [];\n const closeTrigger = new Trigger();\n const sendResponseMessage = createResponseSender(() => connection!);\n\n server.on('connection', (ws) => {\n connection = ws;\n ws.on('error', (err) => log.catch(err));\n ws.on('message', async (data) => {\n if (String(data) === '__ping__') {\n ws.send('__pong__');\n return;\n }\n const { request, requestPayload } = await decodeRequest(params, data);\n if (params?.messageHandler) {\n const responsePayload = await params.messageHandler(requestPayload);\n if (responsePayload && connection) {\n sendResponseMessage(request, responsePayload);\n }\n }\n log('message', { payload: requestPayload });\n messageSink.push(requestPayload);\n });\n\n ws.on('close', () => {\n connection = undefined;\n closeTrigger.wake();\n });\n });\n\n return {\n server,\n messageSink,\n endpoint: `ws://localhost:${port}`,\n cleanup: () => server.close(),\n currentConnection: () => connection,\n sendResponseMessage,\n sendMessage: (msg: Message) => {\n connection!.send(buf.toBinary(MessageSchema, msg));\n },\n closeConnection: () => {\n closeTrigger.reset();\n connection!.close(1011);\n return closeTrigger.wait();\n },\n };\n};\n\nconst createConnectionDelayHandler = (params: TestEdgeWsServerParams | undefined) => {\n return (_: any, callback: (admit: boolean) => void) => {\n if (params?.admitConnection) {\n log('delaying edge connection admission');\n void params.admitConnection.wait().then(() => {\n callback(true);\n log('edge connection admitted');\n });\n } else {\n callback(true);\n }\n };\n};\n\nconst createResponseSender = (connection: () => WebSocket) => {\n return (request: Message, responsePayload: Uint8Array) => {\n const recipient = request.source!;\n connection().send(\n buf.toBinary(\n MessageSchema,\n buf.create(MessageSchema, {\n source: {\n identityKey: recipient.identityKey,\n peerKey: recipient.peerKey,\n },\n serviceId: request.serviceId!,\n payload: { value: responsePayload },\n }),\n ),\n );\n };\n};\n\nconst decodeRequest = async (params: TestEdgeWsServerParams | undefined, data: any) => {\n const request = buf.fromBinary(MessageSchema, await toUint8Array(data));\n const requestPayload = params?.payloadDecoder\n ? params.payloadDecoder(request.payload!.value!)\n : protocol.getPayload(request, TextMessageSchema);\n return { request, requestPayload };\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["DEFAULT_PORT", "createTestEdgeWsServer", "port", "params", "server", "WebSocket", "Server", "verifyClient", "createConnectionDelayHandler", "connection", "messageSink", "closeTrigger", "Trigger", "sendResponseMessage", "createResponseSender", "on", "ws", "err", "log", "catch", "data", "String", "send", "request", "requestPayload", "decodeRequest", "messageHandler", "responsePayload", "payload", "push", "undefined", "wake", "endpoint", "cleanup", "close", "currentConnection", "sendMessage", "msg", "buf", "toBinary", "MessageSchema", "closeConnection", "reset", "wait", "_", "callback", "admitConnection", "then", "recipient", "source", "create", "identityKey", "peerKey", "serviceId", "value", "fromBinary", "toUint8Array", "payloadDecoder", "protocol", "getPayload", "TextMessageSchema"]
7
7
  }