@dxos/client-services 0.6.5 → 0.6.6-main.e1a6e1f

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 (52) hide show
  1. package/dist/lib/browser/{chunk-GIAH3RXX.mjs → chunk-DR3GOD3O.mjs} +907 -442
  2. package/dist/lib/browser/chunk-DR3GOD3O.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +28 -13
  4. package/dist/lib/browser/index.mjs.map +3 -3
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/testing/index.mjs +21 -4
  7. package/dist/lib/browser/testing/index.mjs.map +3 -3
  8. package/dist/lib/node/{chunk-NDXK2NIM.cjs → chunk-DRNEKKQP.cjs} +1065 -607
  9. package/dist/lib/node/chunk-DRNEKKQP.cjs.map +7 -0
  10. package/dist/lib/node/index.cjs +77 -62
  11. package/dist/lib/node/index.cjs.map +3 -3
  12. package/dist/lib/node/meta.json +1 -1
  13. package/dist/lib/node/testing/index.cjs +27 -8
  14. package/dist/lib/node/testing/index.cjs.map +3 -3
  15. package/dist/types/src/packlets/invitations/invitations-handler.d.ts.map +1 -1
  16. package/dist/types/src/packlets/services/service-context.d.ts +6 -1
  17. package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
  18. package/dist/types/src/packlets/services/service-host.d.ts +1 -0
  19. package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
  20. package/dist/types/src/packlets/spaces/data-space-manager.d.ts +29 -12
  21. package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
  22. package/dist/types/src/packlets/spaces/data-space.d.ts +7 -0
  23. package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
  24. package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts +35 -0
  25. package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts.map +1 -0
  26. package/dist/types/src/packlets/spaces/index.d.ts +1 -0
  27. package/dist/types/src/packlets/spaces/index.d.ts.map +1 -1
  28. package/dist/types/src/packlets/testing/invitation-utils.d.ts +2 -0
  29. package/dist/types/src/packlets/testing/invitation-utils.d.ts.map +1 -1
  30. package/dist/types/src/packlets/testing/test-builder.d.ts +3 -1
  31. package/dist/types/src/packlets/testing/test-builder.d.ts.map +1 -1
  32. package/dist/types/src/packlets/worker/worker-runtime.d.ts +8 -3
  33. package/dist/types/src/packlets/worker/worker-runtime.d.ts.map +1 -1
  34. package/dist/types/src/version.d.ts +1 -1
  35. package/dist/types/src/version.d.ts.map +1 -1
  36. package/package.json +38 -36
  37. package/src/packlets/invitations/invitations-handler.test.ts +1 -0
  38. package/src/packlets/invitations/invitations-handler.ts +12 -0
  39. package/src/packlets/invitations/space-invitation-protocol.test.ts +23 -1
  40. package/src/packlets/services/service-context.ts +44 -12
  41. package/src/packlets/services/service-host.ts +26 -4
  42. package/src/packlets/spaces/data-space-manager.test.ts +6 -0
  43. package/src/packlets/spaces/data-space-manager.ts +80 -36
  44. package/src/packlets/spaces/data-space.ts +36 -2
  45. package/src/packlets/spaces/edge-feed-replicator.ts +249 -0
  46. package/src/packlets/spaces/index.ts +1 -0
  47. package/src/packlets/testing/invitation-utils.ts +2 -2
  48. package/src/packlets/testing/test-builder.ts +20 -12
  49. package/src/packlets/worker/worker-runtime.ts +32 -10
  50. package/src/version.ts +1 -5
  51. package/dist/lib/browser/chunk-GIAH3RXX.mjs.map +0 -7
  52. package/dist/lib/node/chunk-NDXK2NIM.cjs.map +0 -7
@@ -18,59 +18,61 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var node_exports = {};
20
20
  __export(node_exports, {
21
- ClientRpcServer: () => import_chunk_NDXK2NIM.ClientRpcServer,
22
- ClientServicesHost: () => import_chunk_NDXK2NIM.ClientServicesHost,
23
- DataSpace: () => import_chunk_NDXK2NIM.DataSpace,
24
- DataSpaceManager: () => import_chunk_NDXK2NIM.DataSpaceManager,
25
- DeviceInvitationProtocol: () => import_chunk_NDXK2NIM.DeviceInvitationProtocol,
26
- DevtoolsHostEvents: () => import_chunk_NDXK2NIM.DevtoolsHostEvents,
27
- DevtoolsServiceImpl: () => import_chunk_NDXK2NIM.DevtoolsServiceImpl,
28
- DiagnosticsCollector: () => import_chunk_NDXK2NIM.DiagnosticsCollector,
29
- Identity: () => import_chunk_NDXK2NIM.Identity,
30
- IdentityManager: () => import_chunk_NDXK2NIM.IdentityManager,
31
- IdentityServiceImpl: () => import_chunk_NDXK2NIM.IdentityServiceImpl,
32
- InvitationsHandler: () => import_chunk_NDXK2NIM.InvitationsHandler,
33
- InvitationsManager: () => import_chunk_NDXK2NIM.InvitationsManager,
34
- InvitationsServiceImpl: () => import_chunk_NDXK2NIM.InvitationsServiceImpl,
35
- Lock: () => import_chunk_NDXK2NIM.Lock,
36
- ServiceContext: () => import_chunk_NDXK2NIM.ServiceContext,
37
- ServiceRegistry: () => import_chunk_NDXK2NIM.ServiceRegistry,
38
- SpaceInvitationProtocol: () => import_chunk_NDXK2NIM.SpaceInvitationProtocol,
39
- SpacesServiceImpl: () => import_chunk_NDXK2NIM.SpacesServiceImpl,
40
- TrustedKeySetAuthVerifier: () => import_chunk_NDXK2NIM.TrustedKeySetAuthVerifier,
21
+ ClientRpcServer: () => import_chunk_DRNEKKQP.ClientRpcServer,
22
+ ClientServicesHost: () => import_chunk_DRNEKKQP.ClientServicesHost,
23
+ DataSpace: () => import_chunk_DRNEKKQP.DataSpace,
24
+ DataSpaceManager: () => import_chunk_DRNEKKQP.DataSpaceManager,
25
+ DeviceInvitationProtocol: () => import_chunk_DRNEKKQP.DeviceInvitationProtocol,
26
+ DevtoolsHostEvents: () => import_chunk_DRNEKKQP.DevtoolsHostEvents,
27
+ DevtoolsServiceImpl: () => import_chunk_DRNEKKQP.DevtoolsServiceImpl,
28
+ DiagnosticsCollector: () => import_chunk_DRNEKKQP.DiagnosticsCollector,
29
+ EdgeFeedReplicator: () => import_chunk_DRNEKKQP.EdgeFeedReplicator,
30
+ Identity: () => import_chunk_DRNEKKQP.Identity,
31
+ IdentityManager: () => import_chunk_DRNEKKQP.IdentityManager,
32
+ IdentityServiceImpl: () => import_chunk_DRNEKKQP.IdentityServiceImpl,
33
+ InvitationsHandler: () => import_chunk_DRNEKKQP.InvitationsHandler,
34
+ InvitationsManager: () => import_chunk_DRNEKKQP.InvitationsManager,
35
+ InvitationsServiceImpl: () => import_chunk_DRNEKKQP.InvitationsServiceImpl,
36
+ Lock: () => import_chunk_DRNEKKQP.Lock,
37
+ ServiceContext: () => import_chunk_DRNEKKQP.ServiceContext,
38
+ ServiceRegistry: () => import_chunk_DRNEKKQP.ServiceRegistry,
39
+ SpaceInvitationProtocol: () => import_chunk_DRNEKKQP.SpaceInvitationProtocol,
40
+ SpacesServiceImpl: () => import_chunk_DRNEKKQP.SpacesServiceImpl,
41
+ TrustedKeySetAuthVerifier: () => import_chunk_DRNEKKQP.TrustedKeySetAuthVerifier,
41
42
  WorkerRuntime: () => WorkerRuntime,
42
43
  WorkerSession: () => WorkerSession,
43
- createAdmissionKeypair: () => import_chunk_NDXK2NIM.createAdmissionKeypair,
44
- createAuthProvider: () => import_chunk_NDXK2NIM.createAuthProvider,
45
- createCollectDiagnosticsBroadcastHandler: () => import_chunk_NDXK2NIM.createCollectDiagnosticsBroadcastHandler,
46
- createCollectDiagnosticsBroadcastSender: () => import_chunk_NDXK2NIM.createCollectDiagnosticsBroadcastSender,
47
- createDiagnostics: () => import_chunk_NDXK2NIM.createDiagnostics,
48
- createLevel: () => import_chunk_NDXK2NIM.createLevel,
49
- createStorageObjects: () => import_chunk_NDXK2NIM.createStorageObjects,
50
- decodeProfileArchive: () => import_chunk_NDXK2NIM.decodeProfileArchive,
51
- encodeProfileArchive: () => import_chunk_NDXK2NIM.encodeProfileArchive,
52
- exportProfileData: () => import_chunk_NDXK2NIM.exportProfileData,
53
- getNetworkPeers: () => import_chunk_NDXK2NIM.getNetworkPeers,
54
- importProfileData: () => import_chunk_NDXK2NIM.importProfileData,
55
- isLocked: () => import_chunk_NDXK2NIM.isLocked,
56
- subscribeToFeedBlocks: () => import_chunk_NDXK2NIM.subscribeToFeedBlocks,
57
- subscribeToFeeds: () => import_chunk_NDXK2NIM.subscribeToFeeds,
58
- subscribeToNetworkStatus: () => import_chunk_NDXK2NIM.subscribeToNetworkStatus,
59
- subscribeToNetworkTopics: () => import_chunk_NDXK2NIM.subscribeToNetworkTopics,
60
- subscribeToSignal: () => import_chunk_NDXK2NIM.subscribeToSignal,
61
- subscribeToSpaces: () => import_chunk_NDXK2NIM.subscribeToSpaces,
62
- subscribeToSwarmInfo: () => import_chunk_NDXK2NIM.subscribeToSwarmInfo
44
+ createAdmissionKeypair: () => import_chunk_DRNEKKQP.createAdmissionKeypair,
45
+ createAuthProvider: () => import_chunk_DRNEKKQP.createAuthProvider,
46
+ createCollectDiagnosticsBroadcastHandler: () => import_chunk_DRNEKKQP.createCollectDiagnosticsBroadcastHandler,
47
+ createCollectDiagnosticsBroadcastSender: () => import_chunk_DRNEKKQP.createCollectDiagnosticsBroadcastSender,
48
+ createDiagnostics: () => import_chunk_DRNEKKQP.createDiagnostics,
49
+ createLevel: () => import_chunk_DRNEKKQP.createLevel,
50
+ createStorageObjects: () => import_chunk_DRNEKKQP.createStorageObjects,
51
+ decodeProfileArchive: () => import_chunk_DRNEKKQP.decodeProfileArchive,
52
+ encodeProfileArchive: () => import_chunk_DRNEKKQP.encodeProfileArchive,
53
+ exportProfileData: () => import_chunk_DRNEKKQP.exportProfileData,
54
+ getNetworkPeers: () => import_chunk_DRNEKKQP.getNetworkPeers,
55
+ importProfileData: () => import_chunk_DRNEKKQP.importProfileData,
56
+ isLocked: () => import_chunk_DRNEKKQP.isLocked,
57
+ subscribeToFeedBlocks: () => import_chunk_DRNEKKQP.subscribeToFeedBlocks,
58
+ subscribeToFeeds: () => import_chunk_DRNEKKQP.subscribeToFeeds,
59
+ subscribeToNetworkStatus: () => import_chunk_DRNEKKQP.subscribeToNetworkStatus,
60
+ subscribeToNetworkTopics: () => import_chunk_DRNEKKQP.subscribeToNetworkTopics,
61
+ subscribeToSignal: () => import_chunk_DRNEKKQP.subscribeToSignal,
62
+ subscribeToSpaces: () => import_chunk_DRNEKKQP.subscribeToSpaces,
63
+ subscribeToSwarmInfo: () => import_chunk_DRNEKKQP.subscribeToSwarmInfo
63
64
  });
64
65
  module.exports = __toCommonJS(node_exports);
65
- var import_chunk_NDXK2NIM = require("./chunk-NDXK2NIM.cjs");
66
+ var import_chunk_DRNEKKQP = require("./chunk-DRNEKKQP.cjs");
66
67
  var import_async = require("@dxos/async");
68
+ var import_client_protocol = require("@dxos/client-protocol");
67
69
  var import_context = require("@dxos/context");
68
70
  var import_invariant = require("@dxos/invariant");
69
71
  var import_log = require("@dxos/log");
70
72
  var import_messaging = require("@dxos/messaging");
71
73
  var import_network_manager = require("@dxos/network-manager");
72
74
  var import_async2 = require("@dxos/async");
73
- var import_client_protocol = require("@dxos/client-protocol");
75
+ var import_client_protocol2 = require("@dxos/client-protocol");
74
76
  var import_invariant2 = require("@dxos/invariant");
75
77
  var import_log2 = require("@dxos/log");
76
78
  var import_rpc = require("@dxos/rpc");
@@ -103,7 +105,7 @@ var WorkerSession = class {
103
105
  const middleware = {
104
106
  handleCall: async (method, params, handler) => {
105
107
  const error = await readySignal.wait({
106
- timeout: import_client_protocol.PROXY_CONNECTION_TIMEOUT
108
+ timeout: import_client_protocol2.PROXY_CONNECTION_TIMEOUT
107
109
  });
108
110
  if (error) {
109
111
  throw error;
@@ -112,7 +114,7 @@ var WorkerSession = class {
112
114
  },
113
115
  handleStream: async (method, params, handler) => {
114
116
  const error = await readySignal.wait({
115
- timeout: import_client_protocol.PROXY_CONNECTION_TIMEOUT
117
+ timeout: import_client_protocol2.PROXY_CONNECTION_TIMEOUT
116
118
  });
117
119
  if (error) {
118
120
  throw error;
@@ -120,19 +122,19 @@ var WorkerSession = class {
120
122
  return handler(method, params);
121
123
  }
122
124
  };
123
- this._clientRpc = new import_chunk_NDXK2NIM.ClientRpcServer({
125
+ this._clientRpc = new import_chunk_DRNEKKQP.ClientRpcServer({
124
126
  serviceRegistry: this._serviceHost.serviceRegistry,
125
127
  port: appPort,
126
128
  ...middleware
127
129
  });
128
- this._shellClientRpc = shellPort ? new import_chunk_NDXK2NIM.ClientRpcServer({
130
+ this._shellClientRpc = shellPort ? new import_chunk_DRNEKKQP.ClientRpcServer({
129
131
  serviceRegistry: this._serviceHost.serviceRegistry,
130
132
  port: shellPort,
131
133
  ...middleware
132
134
  }) : void 0;
133
135
  this._iframeRpc = (0, import_rpc.createProtoRpcPeer)({
134
- requested: import_client_protocol.iframeServiceBundle,
135
- exposed: import_client_protocol.workerServiceBundle,
136
+ requested: import_client_protocol2.iframeServiceBundle,
137
+ exposed: import_client_protocol2.workerServiceBundle,
136
138
  handlers: {
137
139
  WorkerService: {
138
140
  start: async (request) => {
@@ -176,7 +178,7 @@ var WorkerSession = class {
176
178
  this._maybeOpenShell()
177
179
  ]);
178
180
  await this._startTrigger.wait({
179
- timeout: import_client_protocol.PROXY_CONNECTION_TIMEOUT
181
+ timeout: import_client_protocol2.PROXY_CONNECTION_TIMEOUT
180
182
  });
181
183
  if (this.lockKey) {
182
184
  void this._afterLockReleases(this.lockKey, () => this.close());
@@ -241,8 +243,7 @@ _ts_decorate([
241
243
  ], WorkerSession.prototype, "lockKey", void 0);
242
244
  var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/sdk/client-services/src/packlets/worker/worker-runtime.ts";
243
245
  var WorkerRuntime = class {
244
- constructor(_configProvider, { acquireLock, releaseLock, onReset }) {
245
- this._configProvider = _configProvider;
246
+ constructor({ channel = import_client_protocol.DEFAULT_WORKER_BROADCAST_CHANNEL, configProvider, acquireLock, releaseLock, onStop }) {
246
247
  this._transportFactory = new import_network_manager.SimplePeerTransportProxyFactory();
247
248
  this._ready = new import_async.Trigger();
248
249
  this._sessions = /* @__PURE__ */ new Set();
@@ -250,11 +251,14 @@ var WorkerRuntime = class {
250
251
  runtime: "worker-runtime"
251
252
  };
252
253
  this._signalTelemetryEnabled = false;
254
+ this._configProvider = configProvider;
253
255
  this._acquireLock = acquireLock;
254
256
  this._releaseLock = releaseLock;
255
- this._clientServices = new import_chunk_NDXK2NIM.ClientServicesHost({
257
+ this._onStop = onStop;
258
+ this._channel = channel;
259
+ this._clientServices = new import_chunk_DRNEKKQP.ClientServicesHost({
256
260
  callbacks: {
257
- onReset: async () => onReset()
261
+ onReset: async () => this.stop()
258
262
  }
259
263
  });
260
264
  }
@@ -264,11 +268,20 @@ var WorkerRuntime = class {
264
268
  async start() {
265
269
  (0, import_log.log)("starting...", void 0, {
266
270
  F: __dxlog_file2,
267
- L: 71,
271
+ L: 84,
268
272
  S: this,
269
273
  C: (f, a) => f(...a)
270
274
  });
271
275
  try {
276
+ this._broadcastChannel = new BroadcastChannel(this._channel);
277
+ this._broadcastChannel.postMessage({
278
+ action: "stop"
279
+ });
280
+ this._broadcastChannel.onmessage = async (event) => {
281
+ if (event.data?.action === "stop") {
282
+ await this.stop();
283
+ }
284
+ };
272
285
  await this._acquireLock();
273
286
  this._config = await this._configProvider();
274
287
  const signals = this._config.get("runtime.services.signaling");
@@ -279,12 +292,12 @@ var WorkerRuntime = class {
279
292
  });
280
293
  await this._clientServices.open(new import_context.Context(void 0, {
281
294
  F: __dxlog_file2,
282
- L: 84
295
+ L: 105
283
296
  }));
284
297
  this._ready.wake(void 0);
285
298
  (0, import_log.log)("started", void 0, {
286
299
  F: __dxlog_file2,
287
- L: 86,
300
+ L: 107,
288
301
  S: this,
289
302
  C: (f, a) => f(...a)
290
303
  });
@@ -299,7 +312,7 @@ var WorkerRuntime = class {
299
312
  this._ready.wake(err);
300
313
  import_log.log.error("starting", err, {
301
314
  F: __dxlog_file2,
302
- L: 96,
315
+ L: 117,
303
316
  S: this,
304
317
  C: (f, a) => f(...a)
305
318
  });
@@ -307,7 +320,10 @@ var WorkerRuntime = class {
307
320
  }
308
321
  async stop() {
309
322
  this._releaseLock();
323
+ this._broadcastChannel?.close();
324
+ this._broadcastChannel = void 0;
310
325
  await this._clientServices.close();
326
+ await this._onStop?.();
311
327
  }
312
328
  /**
313
329
  * Create a new session.
@@ -323,9 +339,7 @@ var WorkerRuntime = class {
323
339
  session.onClose.set(async () => {
324
340
  this._sessions.delete(session);
325
341
  if (this._sessions.size === 0) {
326
- if (globalThis.self) {
327
- self.close();
328
- }
342
+ await this.stop();
329
343
  } else {
330
344
  this._reconnectWebrtc();
331
345
  }
@@ -333,7 +347,7 @@ var WorkerRuntime = class {
333
347
  await session.open();
334
348
  (0, import_invariant.invariant)(!this._signalMetadataTags.origin || this._signalMetadataTags.origin === session.origin, `worker origin changed from ${this._signalMetadataTags.origin} to ${session.origin}?`, {
335
349
  F: __dxlog_file2,
336
- L: 133,
350
+ L: 155,
337
351
  S: this,
338
352
  A: [
339
353
  "!this._signalMetadataTags.origin || this._signalMetadataTags.origin === session.origin",
@@ -354,7 +368,7 @@ var WorkerRuntime = class {
354
368
  _reconnectWebrtc() {
355
369
  (0, import_log.log)("reconnecting webrtc...", void 0, {
356
370
  F: __dxlog_file2,
357
- L: 151,
371
+ L: 173,
358
372
  S: this,
359
373
  C: (f, a) => f(...a)
360
374
  });
@@ -384,6 +398,7 @@ var WorkerRuntime = class {
384
398
  DevtoolsHostEvents,
385
399
  DevtoolsServiceImpl,
386
400
  DiagnosticsCollector,
401
+ EdgeFeedReplicator,
387
402
  Identity,
388
403
  IdentityManager,
389
404
  IdentityServiceImpl,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/packlets/worker/worker-runtime.ts", "../../../src/packlets/worker/worker-session.ts"],
4
- "sourcesContent": ["//\n// Copyright 2022 DXOS.org\n//\n\nimport { Trigger } from '@dxos/async';\nimport { type Config } from '@dxos/config';\nimport { Context } from '@dxos/context';\nimport { invariant } from '@dxos/invariant';\nimport { log } from '@dxos/log';\nimport {\n MemorySignalManager,\n MemorySignalManagerContext,\n WebsocketSignalManager,\n setIdentityTags,\n} from '@dxos/messaging';\nimport { SimplePeerTransportProxyFactory } from '@dxos/network-manager';\nimport { type RpcPort } from '@dxos/rpc';\nimport { type MaybePromise } from '@dxos/util';\n\nimport { WorkerSession } from './worker-session';\nimport { ClientServicesHost } from '../services';\n\n// NOTE: Keep as RpcPorts to avoid dependency on @dxos/rpc-tunnel so we don't depend on browser-specific apis.\nexport type CreateSessionParams = {\n appPort: RpcPort;\n systemPort: RpcPort;\n shellPort?: RpcPort;\n};\n\nexport type WorkerRuntimeCallbacks = {\n acquireLock: () => Promise<void>;\n releaseLock: () => void;\n onReset: () => Promise<void>;\n};\n\n/**\n * Runtime for the shared worker.\n * Manages connections from proxies (in tabs).\n * Tabs make requests to the `ClientServicesHost`, and provide a WebRTC gateway.\n */\nexport class WorkerRuntime {\n private readonly _acquireLock: () => Promise<void>;\n private readonly _releaseLock: () => void;\n private readonly _transportFactory = new SimplePeerTransportProxyFactory();\n private readonly _ready = new Trigger<Error | undefined>();\n private readonly _sessions = new Set<WorkerSession>();\n private readonly _clientServices!: ClientServicesHost;\n private _sessionForNetworking?: WorkerSession; // TODO(burdon): Expose to client QueryStatusResponse.\n private _config!: Config;\n private _signalMetadataTags: any = { runtime: 'worker-runtime' };\n private _signalTelemetryEnabled: boolean = false;\n\n constructor(\n private readonly _configProvider: () => MaybePromise<Config>,\n { acquireLock, releaseLock, onReset }: WorkerRuntimeCallbacks,\n ) {\n this._acquireLock = acquireLock;\n this._releaseLock = releaseLock;\n this._clientServices = new ClientServicesHost({\n callbacks: {\n onReset: async () => onReset(),\n },\n });\n }\n\n get host() {\n return this._clientServices;\n }\n\n async start() {\n log('starting...');\n try {\n await this._acquireLock();\n this._config = await this._configProvider();\n const signals = this._config.get('runtime.services.signaling');\n this._clientServices.initialize({\n config: this._config,\n signalManager: signals\n ? new WebsocketSignalManager(signals, () => (this._signalTelemetryEnabled ? this._signalMetadataTags : {}))\n : new MemorySignalManager(new MemorySignalManagerContext()), // TODO(dmaretskyi): Inject this context.\n transportFactory: this._transportFactory,\n });\n\n await this._clientServices.open(new Context());\n this._ready.wake(undefined);\n log('started');\n setIdentityTags({\n identityService: this._clientServices.services.IdentityService!,\n devicesService: this._clientServices.services.DevicesService!,\n setTag: (k: string, v: string) => {\n this._signalMetadataTags[k] = v;\n },\n });\n } catch (err: any) {\n this._ready.wake(err);\n log.error('starting', err);\n }\n }\n\n async stop() {\n // Release the lock to notify remote clients that the worker is terminating.\n this._releaseLock();\n await this._clientServices.close();\n }\n\n /**\n * Create a new session.\n */\n async createSession({ appPort, systemPort, shellPort }: CreateSessionParams) {\n const session = new WorkerSession({\n serviceHost: this._clientServices,\n appPort,\n systemPort,\n shellPort,\n readySignal: this._ready,\n });\n\n // When tab is closed or client is destroyed.\n session.onClose.set(async () => {\n this._sessions.delete(session);\n if (this._sessions.size === 0) {\n // Terminate the worker when all sessions are closed.\n if (globalThis.self) {\n self.close();\n }\n } else {\n this._reconnectWebrtc();\n }\n });\n\n await session.open();\n // A worker can only service one origin currently\n invariant(\n !this._signalMetadataTags.origin || this._signalMetadataTags.origin === session.origin,\n `worker origin changed from ${this._signalMetadataTags.origin} to ${session.origin}?`,\n );\n if (session.observabilityGroup) {\n this._signalMetadataTags.group = session.observabilityGroup;\n }\n this._signalTelemetryEnabled = session.signalTelemetryEnabled ?? false;\n this._signalMetadataTags.origin = session.origin;\n this._sessions.add(session);\n\n this._reconnectWebrtc();\n }\n\n /**\n * Selects one of the existing session for WebRTC networking.\n */\n private _reconnectWebrtc() {\n log('reconnecting webrtc...');\n // Check if current session is already closed.\n if (this._sessionForNetworking) {\n if (!this._sessions.has(this._sessionForNetworking)) {\n this._sessionForNetworking = undefined;\n }\n }\n\n // Select existing session.\n if (!this._sessionForNetworking) {\n const selected = Array.from(this._sessions).find((session) => session.bridgeService);\n if (selected) {\n this._sessionForNetworking = selected;\n this._transportFactory.setBridgeService(selected.bridgeService);\n } else {\n this._transportFactory.setBridgeService(undefined);\n }\n }\n }\n}\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport { asyncTimeout, Trigger } from '@dxos/async';\nimport {\n iframeServiceBundle,\n type IframeServiceBundle,\n PROXY_CONNECTION_TIMEOUT,\n workerServiceBundle,\n} from '@dxos/client-protocol';\nimport { invariant } from '@dxos/invariant';\nimport { log, logInfo } from '@dxos/log';\nimport { type BridgeService } from '@dxos/protocols/proto/dxos/mesh/bridge';\nimport { createProtoRpcPeer, type ProtoRpcPeer, type RpcPort } from '@dxos/rpc';\nimport { Callback, type MaybePromise } from '@dxos/util';\n\nimport { type ClientServicesHost, ClientRpcServer, type ClientRpcServerParams } from '../services';\n\nexport type WorkerSessionParams = {\n serviceHost: ClientServicesHost;\n systemPort: RpcPort;\n appPort: RpcPort;\n // TODO(wittjosiah): Remove shellPort.\n shellPort?: RpcPort;\n readySignal: Trigger<Error | undefined>;\n};\n\n/**\n * Represents a tab connection within the worker.\n */\nexport class WorkerSession {\n private readonly _clientRpc: ClientRpcServer;\n private readonly _shellClientRpc?: ClientRpcServer;\n private readonly _iframeRpc: ProtoRpcPeer<IframeServiceBundle>;\n private readonly _startTrigger = new Trigger();\n private readonly _serviceHost: ClientServicesHost;\n\n public readonly onClose = new Callback<() => Promise<void>>();\n\n @logInfo\n public origin?: string;\n\n // TODO(nf): factor out?\n public observabilityGroup?: string;\n public signalTelemetryEnabled?: boolean;\n\n @logInfo\n public lockKey?: string;\n\n public bridgeService?: BridgeService;\n\n constructor({ serviceHost, systemPort, appPort, shellPort, readySignal }: WorkerSessionParams) {\n invariant(serviceHost);\n this._serviceHost = serviceHost;\n\n const middleware: Pick<ClientRpcServerParams, 'handleCall' | 'handleStream'> = {\n handleCall: async (method, params, handler) => {\n const error = await readySignal.wait({ timeout: PROXY_CONNECTION_TIMEOUT });\n if (error) {\n throw error;\n }\n\n return handler(method, params);\n },\n handleStream: async (method, params, handler) => {\n const error = await readySignal.wait({ timeout: PROXY_CONNECTION_TIMEOUT });\n if (error) {\n throw error;\n }\n\n return handler(method, params);\n },\n };\n\n this._clientRpc = new ClientRpcServer({\n serviceRegistry: this._serviceHost.serviceRegistry,\n port: appPort,\n ...middleware,\n });\n\n this._shellClientRpc = shellPort\n ? new ClientRpcServer({\n serviceRegistry: this._serviceHost.serviceRegistry,\n port: shellPort,\n ...middleware,\n })\n : undefined;\n\n this._iframeRpc = createProtoRpcPeer({\n requested: iframeServiceBundle,\n exposed: workerServiceBundle,\n handlers: {\n WorkerService: {\n start: async (request) => {\n this.origin = request.origin;\n this.lockKey = request.lockKey;\n this.observabilityGroup = request.observabilityGroup;\n this.signalTelemetryEnabled = request.signalTelemetryEnabled;\n this._startTrigger.wake();\n },\n\n stop: async () => {\n setTimeout(async () => {\n try {\n await this.close();\n } catch (err: any) {\n log.catch(err);\n }\n });\n },\n },\n },\n port: systemPort,\n timeout: 1_000, // With low timeout heartbeat may fail if the tab's thread is saturated.\n });\n\n this.bridgeService = this._iframeRpc.rpc.BridgeService;\n }\n\n async open() {\n log.info('opening...');\n await Promise.all([this._clientRpc.open(), this._iframeRpc.open(), this._maybeOpenShell()]);\n\n // Wait until the worker's RPC service has started.\n await this._startTrigger.wait({ timeout: PROXY_CONNECTION_TIMEOUT });\n\n // TODO(burdon): Comment required.\n if (this.lockKey) {\n void this._afterLockReleases(this.lockKey, () => this.close());\n }\n\n log.info('opened');\n }\n\n async close() {\n log.info('closing...');\n try {\n await this.onClose.callIfSet();\n } catch (err: any) {\n log.catch(err);\n }\n\n await Promise.all([this._clientRpc.close(), this._iframeRpc.close()]);\n log.info('closed');\n }\n\n private async _maybeOpenShell() {\n try {\n this._shellClientRpc && (await asyncTimeout(this._shellClientRpc.open(), 1_000));\n } catch {\n log.info('No shell connected.');\n }\n }\n\n private _afterLockReleases(lockKey: string, callback: () => MaybePromise<void>): Promise<void> {\n return navigator.locks\n .request(lockKey, () => {\n // No-op.\n })\n .then(callback);\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["import_async", "import_invariant", "import_log", "WorkerSession", "constructor", "serviceHost", "systemPort", "appPort", "shellPort", "readySignal", "_startTrigger", "Trigger", "onClose", "Callback", "invariant", "_serviceHost", "middleware", "handleCall", "method", "params", "handler", "error", "wait", "timeout", "PROXY_CONNECTION_TIMEOUT", "handleStream", "_clientRpc", "ClientRpcServer", "serviceRegistry", "port", "_shellClientRpc", "undefined", "_iframeRpc", "createProtoRpcPeer", "requested", "iframeServiceBundle", "exposed", "workerServiceBundle", "handlers", "WorkerService", "start", "request", "origin", "lockKey", "observabilityGroup", "signalTelemetryEnabled", "wake", "stop", "setTimeout", "close", "err", "log", "catch", "bridgeService", "rpc", "BridgeService", "open", "info", "Promise", "all", "_maybeOpenShell", "_afterLockReleases", "callIfSet", "asyncTimeout", "callback", "navigator", "locks", "then", "logInfo", "WorkerRuntime", "_configProvider", "acquireLock", "releaseLock", "onReset", "_transportFactory", "SimplePeerTransportProxyFactory", "_ready", "_sessions", "Set", "_signalMetadataTags", "runtime", "_signalTelemetryEnabled", "_acquireLock", "_releaseLock", "_clientServices", "ClientServicesHost", "callbacks", "host", "_config", "signals", "get", "initialize", "config", "signalManager", "WebsocketSignalManager", "MemorySignalManager", "MemorySignalManagerContext", "transportFactory", "Context", "setIdentityTags", "identityService", "services", "IdentityService", "devicesService", "DevicesService", "setTag", "k", "v", "createSession", "session", "set", "delete", "size", "globalThis", "self", "_reconnectWebrtc", "group", "add", "_sessionForNetworking", "has", "selected", "Array", "from", "find", "setBridgeService"]
4
+ "sourcesContent": ["//\n// Copyright 2022 DXOS.org\n//\n\nimport { Trigger } from '@dxos/async';\nimport { DEFAULT_WORKER_BROADCAST_CHANNEL } from '@dxos/client-protocol';\nimport { type Config } from '@dxos/config';\nimport { Context } from '@dxos/context';\nimport { invariant } from '@dxos/invariant';\nimport { log } from '@dxos/log';\nimport {\n MemorySignalManager,\n MemorySignalManagerContext,\n WebsocketSignalManager,\n setIdentityTags,\n} from '@dxos/messaging';\nimport { SimplePeerTransportProxyFactory } from '@dxos/network-manager';\nimport { type RpcPort } from '@dxos/rpc';\nimport { type MaybePromise } from '@dxos/util';\n\nimport { WorkerSession } from './worker-session';\nimport { ClientServicesHost } from '../services';\n\n// NOTE: Keep as RpcPorts to avoid dependency on @dxos/rpc-tunnel so we don't depend on browser-specific apis.\nexport type CreateSessionParams = {\n appPort: RpcPort;\n systemPort: RpcPort;\n shellPort?: RpcPort;\n};\n\nexport type WorkerRuntimeOptions = {\n channel?: string;\n configProvider: () => MaybePromise<Config>;\n acquireLock: () => Promise<void>;\n releaseLock: () => void;\n onStop?: () => Promise<void>;\n};\n\n/**\n * Runtime for the shared worker.\n * Manages connections from proxies (in tabs).\n * Tabs make requests to the `ClientServicesHost`, and provide a WebRTC gateway.\n */\nexport class WorkerRuntime {\n private readonly _configProvider: () => MaybePromise<Config>;\n private readonly _acquireLock: () => Promise<void>;\n private readonly _releaseLock: () => void;\n private readonly _onStop?: () => Promise<void>;\n private readonly _transportFactory = new SimplePeerTransportProxyFactory();\n private readonly _ready = new Trigger<Error | undefined>();\n private readonly _sessions = new Set<WorkerSession>();\n private readonly _clientServices!: ClientServicesHost;\n private readonly _channel: string;\n private _broadcastChannel?: BroadcastChannel;\n private _sessionForNetworking?: WorkerSession; // TODO(burdon): Expose to client QueryStatusResponse.\n private _config!: Config;\n private _signalMetadataTags: any = { runtime: 'worker-runtime' };\n private _signalTelemetryEnabled: boolean = false;\n\n constructor({\n channel = DEFAULT_WORKER_BROADCAST_CHANNEL,\n configProvider,\n acquireLock,\n releaseLock,\n onStop,\n }: WorkerRuntimeOptions) {\n this._configProvider = configProvider;\n this._acquireLock = acquireLock;\n this._releaseLock = releaseLock;\n this._onStop = onStop;\n this._channel = channel;\n this._clientServices = new ClientServicesHost({\n callbacks: {\n onReset: async () => this.stop(),\n },\n });\n }\n\n get host() {\n return this._clientServices;\n }\n\n async start() {\n log('starting...');\n try {\n this._broadcastChannel = new BroadcastChannel(this._channel);\n this._broadcastChannel.postMessage({ action: 'stop' });\n this._broadcastChannel.onmessage = async (event) => {\n if (event.data?.action === 'stop') {\n await this.stop();\n }\n };\n\n await this._acquireLock();\n this._config = await this._configProvider();\n const signals = this._config.get('runtime.services.signaling');\n this._clientServices.initialize({\n config: this._config,\n signalManager: signals\n ? new WebsocketSignalManager(signals, () => (this._signalTelemetryEnabled ? this._signalMetadataTags : {}))\n : new MemorySignalManager(new MemorySignalManagerContext()), // TODO(dmaretskyi): Inject this context.\n transportFactory: this._transportFactory,\n });\n\n await this._clientServices.open(new Context());\n this._ready.wake(undefined);\n log('started');\n setIdentityTags({\n identityService: this._clientServices.services.IdentityService!,\n devicesService: this._clientServices.services.DevicesService!,\n setTag: (k: string, v: string) => {\n this._signalMetadataTags[k] = v;\n },\n });\n } catch (err: any) {\n this._ready.wake(err);\n log.error('starting', err);\n }\n }\n\n async stop() {\n // Release the lock to notify remote clients that the worker is terminating.\n this._releaseLock();\n this._broadcastChannel?.close();\n this._broadcastChannel = undefined;\n await this._clientServices.close();\n await this._onStop?.();\n }\n\n /**\n * Create a new session.\n */\n async createSession({ appPort, systemPort, shellPort }: CreateSessionParams) {\n const session = new WorkerSession({\n serviceHost: this._clientServices,\n appPort,\n systemPort,\n shellPort,\n readySignal: this._ready,\n });\n\n // When tab is closed or client is destroyed.\n session.onClose.set(async () => {\n this._sessions.delete(session);\n if (this._sessions.size === 0) {\n // Terminate the worker when all sessions are closed.\n await this.stop();\n } else {\n this._reconnectWebrtc();\n }\n });\n\n await session.open();\n // A worker can only service one origin currently\n invariant(\n !this._signalMetadataTags.origin || this._signalMetadataTags.origin === session.origin,\n `worker origin changed from ${this._signalMetadataTags.origin} to ${session.origin}?`,\n );\n if (session.observabilityGroup) {\n this._signalMetadataTags.group = session.observabilityGroup;\n }\n this._signalTelemetryEnabled = session.signalTelemetryEnabled ?? false;\n this._signalMetadataTags.origin = session.origin;\n this._sessions.add(session);\n\n this._reconnectWebrtc();\n }\n\n /**\n * Selects one of the existing session for WebRTC networking.\n */\n private _reconnectWebrtc() {\n log('reconnecting webrtc...');\n // Check if current session is already closed.\n if (this._sessionForNetworking) {\n if (!this._sessions.has(this._sessionForNetworking)) {\n this._sessionForNetworking = undefined;\n }\n }\n\n // Select existing session.\n if (!this._sessionForNetworking) {\n const selected = Array.from(this._sessions).find((session) => session.bridgeService);\n if (selected) {\n this._sessionForNetworking = selected;\n this._transportFactory.setBridgeService(selected.bridgeService);\n } else {\n this._transportFactory.setBridgeService(undefined);\n }\n }\n }\n}\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport { asyncTimeout, Trigger } from '@dxos/async';\nimport {\n iframeServiceBundle,\n type IframeServiceBundle,\n PROXY_CONNECTION_TIMEOUT,\n workerServiceBundle,\n} from '@dxos/client-protocol';\nimport { invariant } from '@dxos/invariant';\nimport { log, logInfo } from '@dxos/log';\nimport { type BridgeService } from '@dxos/protocols/proto/dxos/mesh/bridge';\nimport { createProtoRpcPeer, type ProtoRpcPeer, type RpcPort } from '@dxos/rpc';\nimport { Callback, type MaybePromise } from '@dxos/util';\n\nimport { type ClientServicesHost, ClientRpcServer, type ClientRpcServerParams } from '../services';\n\nexport type WorkerSessionParams = {\n serviceHost: ClientServicesHost;\n systemPort: RpcPort;\n appPort: RpcPort;\n // TODO(wittjosiah): Remove shellPort.\n shellPort?: RpcPort;\n readySignal: Trigger<Error | undefined>;\n};\n\n/**\n * Represents a tab connection within the worker.\n */\nexport class WorkerSession {\n private readonly _clientRpc: ClientRpcServer;\n private readonly _shellClientRpc?: ClientRpcServer;\n private readonly _iframeRpc: ProtoRpcPeer<IframeServiceBundle>;\n private readonly _startTrigger = new Trigger();\n private readonly _serviceHost: ClientServicesHost;\n\n public readonly onClose = new Callback<() => Promise<void>>();\n\n @logInfo\n public origin?: string;\n\n // TODO(nf): factor out?\n public observabilityGroup?: string;\n public signalTelemetryEnabled?: boolean;\n\n @logInfo\n public lockKey?: string;\n\n public bridgeService?: BridgeService;\n\n constructor({ serviceHost, systemPort, appPort, shellPort, readySignal }: WorkerSessionParams) {\n invariant(serviceHost);\n this._serviceHost = serviceHost;\n\n const middleware: Pick<ClientRpcServerParams, 'handleCall' | 'handleStream'> = {\n handleCall: async (method, params, handler) => {\n const error = await readySignal.wait({ timeout: PROXY_CONNECTION_TIMEOUT });\n if (error) {\n throw error;\n }\n\n return handler(method, params);\n },\n handleStream: async (method, params, handler) => {\n const error = await readySignal.wait({ timeout: PROXY_CONNECTION_TIMEOUT });\n if (error) {\n throw error;\n }\n\n return handler(method, params);\n },\n };\n\n this._clientRpc = new ClientRpcServer({\n serviceRegistry: this._serviceHost.serviceRegistry,\n port: appPort,\n ...middleware,\n });\n\n this._shellClientRpc = shellPort\n ? new ClientRpcServer({\n serviceRegistry: this._serviceHost.serviceRegistry,\n port: shellPort,\n ...middleware,\n })\n : undefined;\n\n this._iframeRpc = createProtoRpcPeer({\n requested: iframeServiceBundle,\n exposed: workerServiceBundle,\n handlers: {\n WorkerService: {\n start: async (request) => {\n this.origin = request.origin;\n this.lockKey = request.lockKey;\n this.observabilityGroup = request.observabilityGroup;\n this.signalTelemetryEnabled = request.signalTelemetryEnabled;\n this._startTrigger.wake();\n },\n\n stop: async () => {\n setTimeout(async () => {\n try {\n await this.close();\n } catch (err: any) {\n log.catch(err);\n }\n });\n },\n },\n },\n port: systemPort,\n timeout: 1_000, // With low timeout heartbeat may fail if the tab's thread is saturated.\n });\n\n this.bridgeService = this._iframeRpc.rpc.BridgeService;\n }\n\n async open() {\n log.info('opening...');\n await Promise.all([this._clientRpc.open(), this._iframeRpc.open(), this._maybeOpenShell()]);\n\n // Wait until the worker's RPC service has started.\n await this._startTrigger.wait({ timeout: PROXY_CONNECTION_TIMEOUT });\n\n // TODO(burdon): Comment required.\n if (this.lockKey) {\n void this._afterLockReleases(this.lockKey, () => this.close());\n }\n\n log.info('opened');\n }\n\n async close() {\n log.info('closing...');\n try {\n await this.onClose.callIfSet();\n } catch (err: any) {\n log.catch(err);\n }\n\n await Promise.all([this._clientRpc.close(), this._iframeRpc.close()]);\n log.info('closed');\n }\n\n private async _maybeOpenShell() {\n try {\n this._shellClientRpc && (await asyncTimeout(this._shellClientRpc.open(), 1_000));\n } catch {\n log.info('No shell connected.');\n }\n }\n\n private _afterLockReleases(lockKey: string, callback: () => MaybePromise<void>): Promise<void> {\n return navigator.locks\n .request(lockKey, () => {\n // No-op.\n })\n .then(callback);\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["import_async", "import_client_protocol", "import_invariant", "import_log", "WorkerSession", "constructor", "serviceHost", "systemPort", "appPort", "shellPort", "readySignal", "_startTrigger", "Trigger", "onClose", "Callback", "invariant", "_serviceHost", "middleware", "handleCall", "method", "params", "handler", "error", "wait", "timeout", "PROXY_CONNECTION_TIMEOUT", "handleStream", "_clientRpc", "ClientRpcServer", "serviceRegistry", "port", "_shellClientRpc", "undefined", "_iframeRpc", "createProtoRpcPeer", "requested", "iframeServiceBundle", "exposed", "workerServiceBundle", "handlers", "WorkerService", "start", "request", "origin", "lockKey", "observabilityGroup", "signalTelemetryEnabled", "wake", "stop", "setTimeout", "close", "err", "log", "catch", "bridgeService", "rpc", "BridgeService", "open", "info", "Promise", "all", "_maybeOpenShell", "_afterLockReleases", "callIfSet", "asyncTimeout", "callback", "navigator", "locks", "then", "logInfo", "WorkerRuntime", "channel", "DEFAULT_WORKER_BROADCAST_CHANNEL", "configProvider", "acquireLock", "releaseLock", "onStop", "_transportFactory", "SimplePeerTransportProxyFactory", "_ready", "_sessions", "Set", "_signalMetadataTags", "runtime", "_signalTelemetryEnabled", "_configProvider", "_acquireLock", "_releaseLock", "_onStop", "_channel", "_clientServices", "ClientServicesHost", "callbacks", "onReset", "host", "_broadcastChannel", "BroadcastChannel", "postMessage", "action", "onmessage", "event", "data", "_config", "signals", "get", "initialize", "config", "signalManager", "WebsocketSignalManager", "MemorySignalManager", "MemorySignalManagerContext", "transportFactory", "Context", "setIdentityTags", "identityService", "services", "IdentityService", "devicesService", "DevicesService", "setTag", "k", "v", "createSession", "session", "set", "delete", "size", "_reconnectWebrtc", "group", "add", "_sessionForNetworking", "has", "selected", "Array", "from", "find", "setBridgeService"]
7
7
  }