@dxos/client-services 0.1.19 → 0.1.21

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 (49) hide show
  1. package/dist/lib/browser/index.mjs +306 -129
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node/index.cjs +333 -152
  5. package/dist/lib/node/index.cjs.map +4 -4
  6. package/dist/lib/node/meta.json +1 -1
  7. package/dist/types/src/packlets/identity/identity-manager.d.ts.map +1 -1
  8. package/dist/types/src/packlets/identity/identity.d.ts.map +1 -1
  9. package/dist/types/src/packlets/invitations/space-invitations-handler.d.ts.map +1 -1
  10. package/dist/types/src/packlets/network/index.d.ts +2 -0
  11. package/dist/types/src/packlets/network/index.d.ts.map +1 -0
  12. package/dist/types/src/packlets/network/network-service.d.ts +10 -0
  13. package/dist/types/src/packlets/network/network-service.d.ts.map +1 -0
  14. package/dist/types/src/packlets/services/service-context.d.ts +2 -1
  15. package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
  16. package/dist/types/src/packlets/services/service-definitions.d.ts +2 -1
  17. package/dist/types/src/packlets/services/service-definitions.d.ts.map +1 -1
  18. package/dist/types/src/packlets/services/service-host.d.ts +4 -1
  19. package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
  20. package/dist/types/src/packlets/services/service-host.test.d.ts +2 -0
  21. package/dist/types/src/packlets/services/service-host.test.d.ts.map +1 -0
  22. package/dist/types/src/packlets/spaces/data-space-manager.d.ts +4 -2
  23. package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
  24. package/dist/types/src/packlets/spaces/data-space.d.ts +13 -6
  25. package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
  26. package/dist/types/src/packlets/spaces/spaces-service.d.ts +6 -1
  27. package/dist/types/src/packlets/spaces/spaces-service.d.ts.map +1 -1
  28. package/dist/types/src/packlets/storage/storage.d.ts +0 -2
  29. package/dist/types/src/packlets/storage/storage.d.ts.map +1 -1
  30. package/dist/types/src/packlets/vault/worker-session.d.ts.map +1 -1
  31. package/package.json +28 -34
  32. package/src/packlets/deprecated/space.ts +1 -1
  33. package/src/packlets/devtools/spaces.ts +1 -1
  34. package/src/packlets/identity/identity-manager.ts +3 -9
  35. package/src/packlets/identity/identity.test.ts +4 -33
  36. package/src/packlets/identity/identity.ts +26 -18
  37. package/src/packlets/invitations/space-invitations-handler.test.ts +53 -1
  38. package/src/packlets/invitations/space-invitations-handler.ts +9 -5
  39. package/src/packlets/network/index.ts +5 -0
  40. package/src/packlets/network/network-service.ts +24 -0
  41. package/src/packlets/services/service-context.ts +9 -2
  42. package/src/packlets/services/service-definitions.ts +5 -1
  43. package/src/packlets/services/service-host.test.ts +31 -0
  44. package/src/packlets/services/service-host.ts +13 -9
  45. package/src/packlets/spaces/data-space-manager.ts +46 -9
  46. package/src/packlets/spaces/data-space.ts +28 -10
  47. package/src/packlets/spaces/spaces-service.ts +21 -0
  48. package/src/packlets/storage/storage.ts +4 -41
  49. package/src/packlets/vault/worker-session.ts +1 -0
@@ -18,6 +18,10 @@ var __copyProps = (to, from, except, desc) => {
18
18
  return to;
19
19
  };
20
20
  var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
21
25
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
22
26
  mod
23
27
  ));
@@ -114,7 +118,7 @@ var SpaceServiceImpl = class {
114
118
  identityKey: member.key,
115
119
  displayName: (_b = (_a = member.assertion.profile) == null ? void 0 : _a.displayName) != null ? _b : (0, import_util.humanize)(member.key)
116
120
  },
117
- presenceState: ((_c = this.serviceContext.identityManager.identity) == null ? void 0 : _c.identityKey.equals(member.key)) || space.presence.getPeersOnline().filter(({ identityKey }) => identityKey.equals(member.key)).length > 0 ? import_client.SpaceMember.PresenceState.ONLINE : import_client.SpaceMember.PresenceState.OFFLINE
121
+ presence: ((_c = this.serviceContext.identityManager.identity) == null ? void 0 : _c.identityKey.equals(member.key)) || space.presence.getPeersOnline().filter(({ identityKey }) => identityKey.equals(member.key)).length > 0 ? import_client.SpaceMember.PresenceState.ONLINE : import_client.SpaceMember.PresenceState.OFFLINE
118
122
  };
119
123
  })
120
124
  }));
@@ -237,11 +241,13 @@ var SystemServiceImpl = class {
237
241
  this._config = _config;
238
242
  this._serviceContext = _serviceContext;
239
243
  }
244
+ // TODO(burdon): Remove.
240
245
  async initSession() {
241
246
  }
242
247
  async getConfig(request) {
243
248
  return this._config.values;
244
249
  }
250
+ // TODO(burdon): Connect to iframe RPC heartbeat for network status?
245
251
  async getStatus(request) {
246
252
  return {
247
253
  message: `ok: ${Date.now()}`
@@ -445,7 +451,7 @@ var subscribeToSpaces = (context, { spaceKeys = [] }) => new import_codec_protob
445
451
  return {
446
452
  key: space.key,
447
453
  isOpen: space.isOpen,
448
- timeframe: spaceMetadata.latestTimeframe,
454
+ timeframe: spaceMetadata == null ? void 0 : spaceMetadata.latestTimeframe,
449
455
  genesisFeed: space.genesisFeedKey,
450
456
  controlFeed: space.controlFeedKey,
451
457
  dataFeed: space.dataFeedKey
@@ -647,35 +653,45 @@ var Identity = class {
647
653
  this._signer = signer;
648
654
  this.identityKey = identityKey;
649
655
  this.deviceKey = deviceKey;
650
- this._deviceStateMachine = new import_credentials2.DeviceStateMachine(this.identityKey, this.deviceKey);
651
- this._profileStateMachine = new import_credentials2.ProfileStateMachine(this.identityKey);
652
- this.space.onCredentialProcessed.set(async (credential) => {
653
- await this._deviceStateMachine.process(credential);
654
- await this._profileStateMachine.process(credential);
655
- this.stateUpdate.emit();
656
- });
656
+ this._deviceStateMachine = this.space.spaceState.registerProcessor(new import_credentials2.DeviceStateMachine({
657
+ identityKey: this.identityKey,
658
+ deviceKey: this.deviceKey,
659
+ onUpdate: () => this.stateUpdate.emit()
660
+ }));
661
+ this._profileStateMachine = this.space.spaceState.registerProcessor(new import_credentials2.ProfileStateMachine({
662
+ identityKey: this.identityKey,
663
+ onUpdate: () => this.stateUpdate.emit()
664
+ }));
657
665
  this.authVerifier = new HaloAuthVerifier({
658
666
  trustedDevicesProvider: () => this.authorizedDeviceKeys,
659
667
  update: this.stateUpdate,
660
668
  authTimeout: AUTH_TIMEOUT
661
669
  });
662
670
  }
671
+ // TODO(burdon): Expose state object?
663
672
  get authorizedDeviceKeys() {
664
- return this._deviceStateMachine.authorizedDeviceKeys;
673
+ return this._deviceStateMachine.processor.authorizedDeviceKeys;
665
674
  }
666
675
  async open() {
676
+ await this._deviceStateMachine.open();
677
+ await this._profileStateMachine.open();
667
678
  await this.space.open();
668
679
  }
669
680
  async close() {
670
681
  await this.authVerifier.close();
682
+ await this._deviceStateMachine.close();
683
+ await this._profileStateMachine.close();
671
684
  await this.space.close();
672
685
  }
673
686
  async ready() {
674
- await this._deviceStateMachine.deviceChainReady.wait();
687
+ await this._deviceStateMachine.processor.deviceChainReady.wait();
675
688
  }
676
689
  get profileDocument() {
677
- return this._profileStateMachine.profile;
690
+ return this._profileStateMachine.processor.profile;
678
691
  }
692
+ /**
693
+ * @test-only
694
+ */
679
695
  get controlPipeline() {
680
696
  return this.space.controlPipeline;
681
697
  }
@@ -692,10 +708,17 @@ var Identity = class {
692
708
  dataFeedKey: this.space.dataFeedKey
693
709
  };
694
710
  }
711
+ /**
712
+ * Issues credentials as identity.
713
+ * Requires identity to be ready.
714
+ */
695
715
  getIdentityCredentialSigner() {
696
- (0, import_node_assert2.default)(this._deviceStateMachine.deviceCredentialChain, "Device credential chain is not ready.");
697
- return (0, import_credentials2.createCredentialSignerWithChain)(this._signer, this._deviceStateMachine.deviceCredentialChain, this.deviceKey);
716
+ (0, import_node_assert2.default)(this._deviceStateMachine.processor.deviceCredentialChain, "Device credential chain is not ready.");
717
+ return (0, import_credentials2.createCredentialSignerWithChain)(this._signer, this._deviceStateMachine.processor.deviceCredentialChain, this.deviceKey);
698
718
  }
719
+ /**
720
+ * Issues credentials as device.
721
+ */
699
722
  getDeviceCredentialSigner() {
700
723
  return (0, import_credentials2.createCredentialSignerWithKey)(this._signer, this.deviceKey);
701
724
  }
@@ -708,7 +731,7 @@ var Identity = class {
708
731
  dataFeedKey
709
732
  }, {
710
733
  file: "identity.ts",
711
- line: 147,
734
+ line: 155,
712
735
  scope: this,
713
736
  callSite: (f, a) => f(...a)
714
737
  });
@@ -753,12 +776,12 @@ var Identity = class {
753
776
  var import_node_assert3 = __toESM(require("node:assert"));
754
777
  var import_async6 = require("@dxos/async");
755
778
  var import_credentials4 = require("@dxos/credentials");
756
- var import_echo_db = require("@dxos/echo-db");
757
779
  var import_log4 = require("@dxos/log");
758
780
  var import_credentials5 = require("@dxos/protocols/proto/dxos/halo/credentials");
759
- var import_teleport_extension_presence = require("@dxos/teleport-extension-presence");
760
781
  var import_util3 = require("@dxos/util");
761
782
  var IdentityManager = class {
783
+ // TODO(burdon): IdentityManagerParams.
784
+ // TODO(dmaretskyi): Perhaps this should take/generate the peerKey outside of an initialized identity.
762
785
  constructor(_metadataStore, _keyring, _spaceManager) {
763
786
  this._metadataStore = _metadataStore;
764
787
  this._keyring = _keyring;
@@ -771,6 +794,14 @@ var IdentityManager = class {
771
794
  async open() {
772
795
  await this._metadataStore.load();
773
796
  const identityRecord = this._metadataStore.getIdentityRecord();
797
+ (0, import_log4.log)("identity record", {
798
+ identityRecord
799
+ }, {
800
+ file: "identity-manager.ts",
801
+ line: 57,
802
+ scope: this,
803
+ callSite: (f, a) => f(...a)
804
+ });
774
805
  if (identityRecord) {
775
806
  this._identity = await this._constructIdentity(identityRecord);
776
807
  await this._identity.open();
@@ -806,7 +837,9 @@ var IdentityManager = class {
806
837
  {
807
838
  const generator = new import_credentials4.CredentialGenerator(this._keyring, identityRecord.identityKey, identityRecord.deviceKey);
808
839
  const credentials = [
840
+ // Space genesis.
809
841
  ...await generator.createSpaceGenesis(identityRecord.haloSpace.spaceKey, identityRecord.haloSpace.genesisFeedKey),
842
+ // Feed admission.
810
843
  await generator.createFeedAdmission(identityRecord.haloSpace.spaceKey, identityRecord.haloSpace.writeDataFeedKey, import_credentials5.AdmittedFeed.Designation.DATA)
811
844
  ];
812
845
  if (displayName) {
@@ -837,6 +870,9 @@ var IdentityManager = class {
837
870
  });
838
871
  return identity;
839
872
  }
873
+ /**
874
+ * Accept an existing identity. Expects it's device key to be authorized (now or later).
875
+ */
840
876
  async acceptIdentity(params) {
841
877
  (0, import_log4.log)("accepting identity", {
842
878
  params
@@ -907,14 +943,9 @@ var IdentityManager = class {
907
943
  controlFeedKey: spaceRecord.writeControlFeedKey,
908
944
  dataFeedKey: spaceRecord.writeDataFeedKey
909
945
  },
910
- dataPipelineControllerProvider: () => new import_echo_db.NoopDataPipelineController(),
911
946
  swarmIdentity,
912
- presence: new import_teleport_extension_presence.Presence({
913
- localPeerId: swarmIdentity.peerKey,
914
- announceInterval: 1e3,
915
- offlineTimeout: 3e4,
916
- identityKey
917
- })
947
+ onNetworkConnection: () => {
948
+ }
918
949
  });
919
950
  }
920
951
  };
@@ -963,6 +994,7 @@ var InvitationObservableProvider = class extends import_async7.CancellableObserv
963
994
  }
964
995
  };
965
996
  var AuthenticatingInvitationProvider = class extends InvitationObservableProvider {
997
+ // prettier-ignore
966
998
  constructor(_actions) {
967
999
  super(() => this._actions.onCancel());
968
1000
  this._actions = _actions;
@@ -989,6 +1021,7 @@ var wrapObservable = async (observable) => {
989
1021
 
990
1022
  // packages/sdk/client-services/src/packlets/invitations/invitations-handler.ts
991
1023
  var AbstractInvitationsHandler = class {
1024
+ // prettier-ignore
992
1025
  constructor(_networkManager) {
993
1026
  this._networkManager = _networkManager;
994
1027
  }
@@ -996,10 +1029,14 @@ var AbstractInvitationsHandler = class {
996
1029
 
997
1030
  // packages/sdk/client-services/src/packlets/invitations/halo-invitations-handler.ts
998
1031
  var HaloInvitationsHandler = class extends AbstractInvitationsHandler {
1032
+ // prettier-ignore
999
1033
  constructor(networkManager, _identityManager) {
1000
1034
  super(networkManager);
1001
1035
  this._identityManager = _identityManager;
1002
1036
  }
1037
+ /**
1038
+ * Creates an invitation and listens for a join request from the invited (guest) peer.
1039
+ */
1003
1040
  createInvitation(context, options) {
1004
1041
  var _a;
1005
1042
  const { type, timeout = INVITATION_TIMEOUT, swarmKey } = options != null ? options : {};
@@ -1055,6 +1092,7 @@ var HaloInvitationsHandler = class extends AbstractInvitationsHandler {
1055
1092
  status: import_invitations.AuthenticationResponse.Status.OK
1056
1093
  };
1057
1094
  },
1095
+ // TODO(burdon): Not used: controlFeedKey, dataFeedKey.
1058
1096
  presentAdmissionCredentials: async (credentials) => {
1059
1097
  try {
1060
1098
  if (invitation.type !== import_services2.Invitation.Type.INTERACTIVE_TESTING) {
@@ -1139,6 +1177,11 @@ var HaloInvitationsHandler = class extends AbstractInvitationsHandler {
1139
1177
  });
1140
1178
  return observable;
1141
1179
  }
1180
+ /**
1181
+ * Waits for the host peer (inviter) to accept our join request.
1182
+ * The local guest peer (invitee) then sends the local halo invitation to the host,
1183
+ * which then writes the guest's credentials to the halo.
1184
+ */
1142
1185
  acceptInvitation(invitation, options) {
1143
1186
  const { timeout = INVITATION_TIMEOUT } = options != null ? options : {};
1144
1187
  const ctx = new import_context2.Context({
@@ -1152,6 +1195,7 @@ var HaloInvitationsHandler = class extends AbstractInvitationsHandler {
1152
1195
  onCancel: async () => {
1153
1196
  await ctx.dispose();
1154
1197
  },
1198
+ // TODO(burdon): Consider retry.
1155
1199
  onAuthenticate: async (code) => {
1156
1200
  authenticated.wake(code);
1157
1201
  }
@@ -1277,6 +1321,8 @@ var HostHaloInvitationExtension = class extends import_teleport.RpcExtension {
1277
1321
  }
1278
1322
  async getHandlers() {
1279
1323
  return {
1324
+ // TODO(dmaretskyi): For now this is just forwarding the data to callbacks since we don't have session-specific logic.
1325
+ // Perhaps in the future we will have more complex logic here.
1280
1326
  HaloHostService: {
1281
1327
  requestAdmission: async () => {
1282
1328
  return this._callbacks.requestAdmission();
@@ -1284,6 +1330,7 @@ var HostHaloInvitationExtension = class extends import_teleport.RpcExtension {
1284
1330
  authenticate: async (credentials) => {
1285
1331
  return this._callbacks.authenticate(credentials);
1286
1332
  },
1333
+ // TODO(burdon): Not used: controlFeedKey, dataFeedKey.
1287
1334
  presentAdmissionCredentials: async (credentials) => {
1288
1335
  return this._callbacks.presentAdmissionCredentials(credentials);
1289
1336
  }
@@ -1319,6 +1366,7 @@ var import_async9 = require("@dxos/async");
1319
1366
  var import_log6 = require("@dxos/log");
1320
1367
  var import_services3 = require("@dxos/protocols/proto/dxos/client/services");
1321
1368
  var AbstractInvitationsProxy = class {
1369
+ // prettier-ignore
1322
1370
  constructor(_invitationsService) {
1323
1371
  this._invitationsService = _invitationsService;
1324
1372
  }
@@ -1459,12 +1507,14 @@ var import_codec_protobuf8 = require("@dxos/codec-protobuf");
1459
1507
  var import_log7 = require("@dxos/log");
1460
1508
  var import_services4 = require("@dxos/protocols/proto/dxos/client/services");
1461
1509
  var AbstractInvitationsService = class {
1510
+ // prettier-ignore
1462
1511
  constructor(_identityManager, _getInvitationsHandler) {
1463
1512
  this._identityManager = _identityManager;
1464
1513
  this._getInvitationsHandler = _getInvitationsHandler;
1465
1514
  this._createInvitations = /* @__PURE__ */ new Map();
1466
1515
  this._acceptInvitations = /* @__PURE__ */ new Map();
1467
1516
  }
1517
+ // TODO(burdon): Guest/host label.
1468
1518
  getLoggingContext() {
1469
1519
  var _a;
1470
1520
  return {
@@ -1674,6 +1724,7 @@ var AbstractInvitationsService = class {
1674
1724
 
1675
1725
  // packages/sdk/client-services/src/packlets/invitations/halo-invitations-service.ts
1676
1726
  var HaloInvitationsServiceImpl = class extends AbstractInvitationsService {
1727
+ // prettier-ignore
1677
1728
  constructor(identityManager, invitationsHandler) {
1678
1729
  super(identityManager, () => invitationsHandler);
1679
1730
  this.invitationsHandler = invitationsHandler;
@@ -1703,6 +1754,9 @@ var SpaceInvitationsHandler = class extends AbstractInvitationsHandler {
1703
1754
  this._signingContext = _signingContext;
1704
1755
  this._keyring = _keyring;
1705
1756
  }
1757
+ /**
1758
+ * Creates an invitation and listens for a join request from the invited (guest) peer.
1759
+ */
1706
1760
  createInvitation(space, options) {
1707
1761
  let swarmConnection;
1708
1762
  const { type, timeout = INVITATION_TIMEOUT, swarmKey } = options != null ? options : {};
@@ -1726,8 +1780,8 @@ var SpaceInvitationsHandler = class extends AbstractInvitationsHandler {
1726
1780
  });
1727
1781
  let authenticationCode;
1728
1782
  let authenticationRetry = 0;
1729
- const complete = new import_async10.Trigger();
1730
1783
  const createExtension = () => {
1784
+ const complete = new import_async10.Trigger();
1731
1785
  let guestProfile;
1732
1786
  const hostInvitationExtension = new HostSpaceInvitationExtension({
1733
1787
  introduce: async ({ profile }) => {
@@ -1738,7 +1792,7 @@ var SpaceInvitationsHandler = class extends AbstractInvitationsHandler {
1738
1792
  spaceKey: space.key
1739
1793
  }, {
1740
1794
  file: "space-invitations-handler.ts",
1741
- line: 98,
1795
+ line: 97,
1742
1796
  scope: this,
1743
1797
  callSite: (f, a) => f(...a)
1744
1798
  });
@@ -1750,7 +1804,7 @@ var SpaceInvitationsHandler = class extends AbstractInvitationsHandler {
1750
1804
  authenticationCode: code
1751
1805
  }, {
1752
1806
  file: "space-invitations-handler.ts",
1753
- line: 112,
1807
+ line: 111,
1754
1808
  scope: this,
1755
1809
  callSite: (f, a) => f(...a)
1756
1810
  });
@@ -1770,7 +1824,7 @@ var SpaceInvitationsHandler = class extends AbstractInvitationsHandler {
1770
1824
  },
1771
1825
  requestAdmission: async ({ identityKey, deviceKey, controlFeedKey, dataFeedKey }) => {
1772
1826
  try {
1773
- if (invitation.type !== import_services5.Invitation.Type.INTERACTIVE_TESTING) {
1827
+ if (invitation.type !== import_services5.Invitation.Type.INTERACTIVE_TESTING && invitation.type !== import_services5.Invitation.Type.MULTIUSE_TESTING) {
1774
1828
  if (invitation.authenticationCode === void 0 || invitation.authenticationCode !== authenticationCode) {
1775
1829
  throw new Error(`invalid authentication code: ${authenticationCode}`);
1776
1830
  }
@@ -1780,7 +1834,7 @@ var SpaceInvitationsHandler = class extends AbstractInvitationsHandler {
1780
1834
  guest: deviceKey
1781
1835
  }, {
1782
1836
  file: "space-invitations-handler.ts",
1783
- line: 136,
1837
+ line: 138,
1784
1838
  scope: this,
1785
1839
  callSite: (f, a) => f(...a)
1786
1840
  });
@@ -1806,7 +1860,7 @@ var SpaceInvitationsHandler = class extends AbstractInvitationsHandler {
1806
1860
  host: this._signingContext.deviceKey
1807
1861
  }, {
1808
1862
  file: "space-invitations-handler.ts",
1809
- line: 170,
1863
+ line: 172,
1810
1864
  scope: this,
1811
1865
  callSite: (f, a) => f(...a)
1812
1866
  });
@@ -1819,7 +1873,7 @@ var SpaceInvitationsHandler = class extends AbstractInvitationsHandler {
1819
1873
  guest: deviceKey
1820
1874
  }, {
1821
1875
  file: "space-invitations-handler.ts",
1822
- line: 173,
1876
+ line: 175,
1823
1877
  scope: this,
1824
1878
  callSite: (f, a) => f(...a)
1825
1879
  });
@@ -1828,15 +1882,17 @@ var SpaceInvitationsHandler = class extends AbstractInvitationsHandler {
1828
1882
  if (!observable.cancelled) {
1829
1883
  import_log8.log.error("failed", err, {
1830
1884
  file: "space-invitations-handler.ts",
1831
- line: 177,
1885
+ line: 179,
1832
1886
  scope: this,
1833
1887
  callSite: (f, a) => f(...a)
1834
1888
  });
1835
1889
  observable.callback.onError(err);
1836
1890
  }
1837
1891
  } finally {
1838
- await (0, import_async10.sleep)(ON_CLOSE_DELAY);
1839
- await ctx.dispose();
1892
+ if (type !== import_services5.Invitation.Type.MULTIUSE_TESTING) {
1893
+ await (0, import_async10.sleep)(ON_CLOSE_DELAY);
1894
+ await ctx.dispose();
1895
+ }
1840
1896
  }
1841
1897
  });
1842
1898
  }
@@ -1859,6 +1915,11 @@ var SpaceInvitationsHandler = class extends AbstractInvitationsHandler {
1859
1915
  });
1860
1916
  return observable;
1861
1917
  }
1918
+ /**
1919
+ * Waits for the host peer (inviter) to accept our join request.
1920
+ * The local guest peer (invitee) then sends the local space invitation to the host,
1921
+ * which then writes the guest's credentials to the space.
1922
+ */
1862
1923
  acceptInvitation(invitation, options) {
1863
1924
  const { timeout = INVITATION_TIMEOUT } = options != null ? options : {};
1864
1925
  const ctx = new import_context3.Context({
@@ -1891,7 +1952,7 @@ var SpaceInvitationsHandler = class extends AbstractInvitationsHandler {
1891
1952
  guest: this._signingContext.deviceKey
1892
1953
  }, {
1893
1954
  file: "space-invitations-handler.ts",
1894
- line: 248,
1955
+ line: 252,
1895
1956
  scope: this,
1896
1957
  callSite: (f, a) => f(...a)
1897
1958
  });
@@ -1900,7 +1961,7 @@ var SpaceInvitationsHandler = class extends AbstractInvitationsHandler {
1900
1961
  guest: this._signingContext.deviceKey
1901
1962
  }, {
1902
1963
  file: "space-invitations-handler.ts",
1903
- line: 252,
1964
+ line: 256,
1904
1965
  scope: this,
1905
1966
  callSite: (f, a) => f(...a)
1906
1967
  });
@@ -1911,7 +1972,7 @@ var SpaceInvitationsHandler = class extends AbstractInvitationsHandler {
1911
1972
  for (let attempt = 1; attempt <= MAX_OTP_ATTEMPTS; attempt++) {
1912
1973
  (0, import_log8.log)("guest waiting for authentication code...", {}, {
1913
1974
  file: "space-invitations-handler.ts",
1914
- line: 261,
1975
+ line: 265,
1915
1976
  scope: this,
1916
1977
  callSite: (f, a) => f(...a)
1917
1978
  });
@@ -1921,7 +1982,7 @@ var SpaceInvitationsHandler = class extends AbstractInvitationsHandler {
1921
1982
  });
1922
1983
  (0, import_log8.log)("sending authentication request", {}, {
1923
1984
  file: "space-invitations-handler.ts",
1924
- line: 265,
1985
+ line: 269,
1925
1986
  scope: this,
1926
1987
  callSite: (f, a) => f(...a)
1927
1988
  });
@@ -1939,7 +2000,7 @@ var SpaceInvitationsHandler = class extends AbstractInvitationsHandler {
1939
2000
  attempt
1940
2001
  }, {
1941
2002
  file: "space-invitations-handler.ts",
1942
- line: 275,
2003
+ line: 279,
1943
2004
  scope: this,
1944
2005
  callSite: (f, a) => f(...a)
1945
2006
  });
@@ -1954,7 +2015,7 @@ var SpaceInvitationsHandler = class extends AbstractInvitationsHandler {
1954
2015
  guest: this._signingContext.deviceKey
1955
2016
  }, {
1956
2017
  file: "space-invitations-handler.ts",
1957
- line: 286,
2018
+ line: 290,
1958
2019
  scope: this,
1959
2020
  callSite: (f, a) => f(...a)
1960
2021
  });
@@ -1978,7 +2039,7 @@ var SpaceInvitationsHandler = class extends AbstractInvitationsHandler {
1978
2039
  spaceKey: space.key
1979
2040
  }, {
1980
2041
  file: "space-invitations-handler.ts",
1981
- line: 309,
2042
+ line: 313,
1982
2043
  scope: this,
1983
2044
  callSite: (f, a) => f(...a)
1984
2045
  });
@@ -1987,7 +2048,7 @@ var SpaceInvitationsHandler = class extends AbstractInvitationsHandler {
1987
2048
  if (!observable.cancelled) {
1988
2049
  import_log8.log.warn("auth failed", err, {
1989
2050
  file: "space-invitations-handler.ts",
1990
- line: 313,
2051
+ line: 317,
1991
2052
  scope: this,
1992
2053
  callSite: (f, a) => f(...a)
1993
2054
  });
@@ -2033,6 +2094,8 @@ var HostSpaceInvitationExtension = class extends import_teleport2.RpcExtension {
2033
2094
  }
2034
2095
  async getHandlers() {
2035
2096
  return {
2097
+ // TODO(dmaretskyi): For now this is just forwarding the data to callbacks since we don't have session-specific logic.
2098
+ // Perhaps in the future we will have more complex logic here.
2036
2099
  SpaceHostService: {
2037
2100
  introduce: async (params) => {
2038
2101
  return this._callbacks.introduce(params);
@@ -2081,6 +2144,7 @@ var SpaceInvitationsProxy = class extends AbstractInvitationsProxy {
2081
2144
  // packages/sdk/client-services/src/packlets/invitations/space-invitations-service.ts
2082
2145
  var import_node_assert9 = __toESM(require("node:assert"));
2083
2146
  var SpaceInvitationsServiceImpl = class extends AbstractInvitationsService {
2147
+ // prettier-ignore
2084
2148
  constructor(identityManager, invitationsHandler, _getSpaceManager) {
2085
2149
  super(identityManager, invitationsHandler);
2086
2150
  this.invitationsHandler = invitationsHandler;
@@ -2096,33 +2160,51 @@ var SpaceInvitationsServiceImpl = class extends AbstractInvitationsService {
2096
2160
  };
2097
2161
 
2098
2162
  // packages/sdk/client-services/src/packlets/services/service-context.ts
2099
- var import_async12 = require("@dxos/async");
2163
+ var import_async13 = require("@dxos/async");
2100
2164
  var import_debug4 = require("@dxos/debug");
2101
- var import_echo_db4 = require("@dxos/echo-db");
2165
+ var import_echo_db3 = require("@dxos/echo-db");
2102
2166
  var import_feed_store4 = require("@dxos/feed-store");
2103
2167
  var import_keyring = require("@dxos/keyring");
2104
2168
  var import_log10 = require("@dxos/log");
2105
2169
 
2106
2170
  // packages/sdk/client-services/src/packlets/spaces/data-space-manager.ts
2107
- var import_async11 = require("@dxos/async");
2108
- var import_echo_db3 = require("@dxos/echo-db");
2171
+ var import_async12 = require("@dxos/async");
2172
+ var import_context5 = require("@dxos/context");
2173
+ var import_echo_db2 = require("@dxos/echo-db");
2109
2174
  var import_keys6 = require("@dxos/keys");
2110
2175
  var import_log9 = require("@dxos/log");
2111
- var import_teleport_extension_presence2 = require("@dxos/teleport-extension-presence");
2176
+ var import_teleport_extension_presence = require("@dxos/teleport-extension-presence");
2112
2177
  var import_util4 = require("@dxos/util");
2113
2178
 
2114
2179
  // packages/sdk/client-services/src/packlets/spaces/data-space.ts
2115
2180
  var import_node_assert10 = __toESM(require("node:assert"));
2181
+ var import_async11 = require("@dxos/async");
2116
2182
  var import_context4 = require("@dxos/context");
2117
- var import_echo_db2 = require("@dxos/echo-db");
2118
- var DataSpace = class {
2119
- constructor(_inner, _modelFactory, _memberKey, _presence) {
2120
- this._inner = _inner;
2121
- this._modelFactory = _modelFactory;
2122
- this._memberKey = _memberKey;
2123
- this._presence = _presence;
2183
+ var import_echo_db = require("@dxos/echo-db");
2184
+ var __decorate = function(decorators, target, key, desc) {
2185
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2186
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
2187
+ r = Reflect.decorate(decorators, target, key, desc);
2188
+ else
2189
+ for (var i = decorators.length - 1; i >= 0; i--)
2190
+ if (d = decorators[i])
2191
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
2192
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
2193
+ };
2194
+ var DataSpace = class DataSpace2 {
2195
+ constructor(params) {
2124
2196
  this._ctx = new import_context4.Context();
2125
- this._dataPipelineController = new import_echo_db2.DataPipelineControllerImpl(_modelFactory, _memberKey, (feedKey) => _inner.spaceState.feeds.get(feedKey));
2197
+ this._inner = params.inner;
2198
+ this._presence = params.presence;
2199
+ this._dataPipelineController = new import_echo_db.DataPipelineControllerImpl({
2200
+ modelFactory: params.modelFactory,
2201
+ metadataStore: params.metadataStore,
2202
+ snapshotManager: params.snapshotManager,
2203
+ memberKey: params.memberKey,
2204
+ spaceKey: this._inner.key,
2205
+ feedInfoProvider: (feedKey) => this._inner.spaceState.feeds.get(feedKey),
2206
+ snapshotId: params.snapshotId
2207
+ });
2126
2208
  }
2127
2209
  get key() {
2128
2210
  return this._inner.key;
@@ -2148,6 +2230,7 @@ var DataSpace = class {
2148
2230
  }
2149
2231
  async open() {
2150
2232
  await this._inner.open();
2233
+ await this._inner.initDataPipeline(this._dataPipelineController);
2151
2234
  }
2152
2235
  async close() {
2153
2236
  await this._ctx.dispose();
@@ -2155,9 +2238,12 @@ var DataSpace = class {
2155
2238
  await this._presence.destroy();
2156
2239
  }
2157
2240
  };
2241
+ DataSpace = __decorate([
2242
+ (0, import_async11.trackLeaks)("open", "close")
2243
+ ], DataSpace);
2158
2244
 
2159
2245
  // packages/sdk/client-services/src/packlets/spaces/data-space-manager.ts
2160
- var __decorate = function(decorators, target, key, desc) {
2246
+ var __decorate2 = function(decorators, target, key, desc) {
2161
2247
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2162
2248
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
2163
2249
  r = Reflect.decorate(decorators, target, key, desc);
@@ -2167,28 +2253,65 @@ var __decorate = function(decorators, target, key, desc) {
2167
2253
  r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
2168
2254
  return c > 3 && r && Object.defineProperty(target, key, r), r;
2169
2255
  };
2170
- var DataSpaceManager = class {
2171
- constructor(_spaceManager, _metadataStore, _dataServiceSubscriptions, _keyring, _signingContext, _modelFactory) {
2256
+ var DataSpaceManager = class DataSpaceManager2 {
2257
+ constructor(_spaceManager, _metadataStore, _dataServiceSubscriptions, _keyring, _signingContext, _modelFactory, _snapshotStore) {
2172
2258
  this._spaceManager = _spaceManager;
2173
2259
  this._metadataStore = _metadataStore;
2174
2260
  this._dataServiceSubscriptions = _dataServiceSubscriptions;
2175
2261
  this._keyring = _keyring;
2176
2262
  this._signingContext = _signingContext;
2177
2263
  this._modelFactory = _modelFactory;
2178
- this.updated = new import_async11.Event();
2264
+ this._snapshotStore = _snapshotStore;
2265
+ this._ctx = new import_context5.Context();
2266
+ this.updated = new import_async12.Event();
2179
2267
  this._spaces = new import_util4.ComplexMap(import_keys6.PublicKey.hash);
2180
2268
  }
2269
+ // TODO(burdon): Remove.
2181
2270
  get spaces() {
2182
2271
  return this._spaces;
2183
2272
  }
2184
2273
  async open() {
2185
2274
  await this._metadataStore.load();
2275
+ (0, import_log9.log)("metadata loaded", {
2276
+ spaces: this._metadataStore.spaces.length
2277
+ }, {
2278
+ file: "data-space-manager.ts",
2279
+ line: 54,
2280
+ scope: this,
2281
+ callSite: (f, a) => f(...a)
2282
+ });
2186
2283
  for (const spaceMetadata of this._metadataStore.spaces) {
2187
- await this._constructSpace(spaceMetadata);
2284
+ (0, import_log9.log)("load space", {
2285
+ spaceMetadata
2286
+ }, {
2287
+ file: "data-space-manager.ts",
2288
+ line: 57,
2289
+ scope: this,
2290
+ callSite: (f, a) => f(...a)
2291
+ });
2292
+ const space = await this._constructSpace(spaceMetadata);
2293
+ if (spaceMetadata.latestTimeframe) {
2294
+ (0, import_log9.log)("waiting for latest timeframe", {
2295
+ spaceMetadata
2296
+ }, {
2297
+ file: "data-space-manager.ts",
2298
+ line: 60,
2299
+ scope: this,
2300
+ callSite: (f, a) => f(...a)
2301
+ });
2302
+ await space.dataPipelineController.waitUntilTimeframe(spaceMetadata.latestTimeframe);
2303
+ }
2188
2304
  }
2189
2305
  }
2190
2306
  async close() {
2307
+ await this._ctx.dispose();
2308
+ for (const space of this._spaces.values()) {
2309
+ await space.close();
2310
+ }
2191
2311
  }
2312
+ /**
2313
+ * Creates a new space writing the genesis credentials to the control feed.
2314
+ */
2192
2315
  async createSpace() {
2193
2316
  const spaceKey = await this._keyring.createKey();
2194
2317
  const controlFeedKey = await this._keyring.createKey();
@@ -2203,16 +2326,17 @@ var DataSpaceManager = class {
2203
2326
  spaceKey
2204
2327
  }, {
2205
2328
  file: "data-space-manager.ts",
2206
- line: 70,
2329
+ line: 89,
2207
2330
  scope: this,
2208
2331
  callSite: (f, a) => f(...a)
2209
2332
  });
2210
2333
  const space = await this._constructSpace(metadata);
2211
- await (0, import_echo_db3.spaceGenesis)(this._keyring, this._signingContext, space.inner);
2334
+ await (0, import_echo_db2.spaceGenesis)(this._keyring, this._signingContext, space.inner);
2212
2335
  await this._metadataStore.addSpace(metadata);
2213
2336
  this.updated.emit();
2214
2337
  return space;
2215
2338
  }
2339
+ // TODO(burdon): Rename join space.
2216
2340
  async acceptSpace(opts) {
2217
2341
  const metadata = {
2218
2342
  key: opts.spaceKey,
@@ -2226,12 +2350,13 @@ var DataSpaceManager = class {
2226
2350
  return space;
2227
2351
  }
2228
2352
  async _constructSpace(metadata) {
2229
- const presence = new import_teleport_extension_presence2.Presence({
2353
+ const presence = new import_teleport_extension_presence.Presence({
2230
2354
  localPeerId: this._signingContext.deviceKey,
2231
2355
  announceInterval: 1e3,
2232
2356
  offlineTimeout: 3e4,
2233
2357
  identityKey: this._signingContext.identityKey
2234
2358
  });
2359
+ const snapshotManager = new import_echo_db2.SnapshotManager(this._snapshotStore);
2235
2360
  const space = await this._spaceManager.constructSpace({
2236
2361
  metadata,
2237
2362
  swarmIdentity: {
@@ -2239,43 +2364,66 @@ var DataSpaceManager = class {
2239
2364
  credentialProvider: this._signingContext.credentialProvider,
2240
2365
  credentialAuthenticator: this._signingContext.credentialAuthenticator
2241
2366
  },
2242
- dataPipelineControllerProvider: () => dataSpace.dataPipelineController,
2243
- presence
2367
+ onNetworkConnection: (session) => {
2368
+ session.addExtension("dxos.mesh.teleport.presence", presence.createExtension({
2369
+ remotePeerId: session.remotePeerId
2370
+ }));
2371
+ session.addExtension("dxos.mesh.teleport.objectsync", snapshotManager.objectSync.createExtension());
2372
+ }
2244
2373
  });
2245
- const dataSpace = new DataSpace(space, this._modelFactory, this._signingContext.identityKey, presence);
2246
- await space.open();
2374
+ const dataSpace = new DataSpace({
2375
+ inner: space,
2376
+ modelFactory: this._modelFactory,
2377
+ metadataStore: this._metadataStore,
2378
+ snapshotManager,
2379
+ presence,
2380
+ memberKey: this._signingContext.identityKey,
2381
+ snapshotId: metadata.snapshot
2382
+ });
2383
+ await dataSpace.open();
2247
2384
  this._dataServiceSubscriptions.registerSpace(space.key, dataSpace.database.createDataServiceHost());
2248
2385
  this._spaces.set(metadata.key, dataSpace);
2249
2386
  return dataSpace;
2250
2387
  }
2251
2388
  };
2252
- __decorate([
2253
- import_async11.synchronized
2389
+ __decorate2([
2390
+ import_async12.synchronized
2254
2391
  ], DataSpaceManager.prototype, "open", null);
2255
- __decorate([
2256
- import_async11.synchronized
2392
+ __decorate2([
2393
+ import_async12.synchronized
2257
2394
  ], DataSpaceManager.prototype, "close", null);
2395
+ __decorate2([
2396
+ import_async12.synchronized
2397
+ ], DataSpaceManager.prototype, "createSpace", null);
2398
+ __decorate2([
2399
+ import_async12.synchronized
2400
+ ], DataSpaceManager.prototype, "acceptSpace", null);
2401
+ DataSpaceManager = __decorate2([
2402
+ (0, import_async12.trackLeaks)("open", "close")
2403
+ ], DataSpaceManager);
2258
2404
 
2259
2405
  // packages/sdk/client-services/src/packlets/services/service-context.ts
2260
2406
  var ServiceContext = class {
2407
+ // prettier-ignore
2261
2408
  constructor(storage, networkManager, modelFactory) {
2262
2409
  this.storage = storage;
2263
2410
  this.networkManager = networkManager;
2264
2411
  this.modelFactory = modelFactory;
2265
- this.initialized = new import_async12.Trigger();
2266
- this.dataServiceSubscriptions = new import_echo_db4.DataServiceSubscriptions();
2267
- this.metadataStore = new import_echo_db4.MetadataStore(storage.createDirectory("metadata"));
2412
+ this.initialized = new import_async13.Trigger();
2413
+ this.dataServiceSubscriptions = new import_echo_db3.DataServiceSubscriptions();
2414
+ this.metadataStore = new import_echo_db3.MetadataStore(storage.createDirectory("metadata"));
2415
+ this.snapshotStore = new import_echo_db3.SnapshotStore(storage.createDirectory("snapshots"));
2268
2416
  this.keyring = new import_keyring.Keyring(storage.createDirectory("keyring"));
2269
2417
  this.feedStore = new import_feed_store4.FeedStore({
2270
2418
  factory: new import_feed_store4.FeedFactory({
2271
2419
  root: storage.createDirectory("feeds"),
2272
2420
  signer: this.keyring,
2273
2421
  hypercore: {
2274
- valueEncoding: import_echo_db4.valueEncoding
2422
+ valueEncoding: import_echo_db3.valueEncoding
2275
2423
  }
2276
2424
  })
2277
2425
  });
2278
- this.spaceManager = new import_echo_db4.SpaceManager({
2426
+ this.spaceManager = new import_echo_db3.SpaceManager({
2279
2427
  feedStore: this.feedStore,
2280
2428
  networkManager: this.networkManager
2281
2429
  });
@@ -2285,10 +2433,11 @@ var ServiceContext = class {
2285
2433
  async open() {
2286
2434
  (0, import_log10.log)("opening...", {}, {
2287
2435
  file: "service-context.ts",
2288
- line: 81,
2436
+ line: 85,
2289
2437
  scope: this,
2290
2438
  callSite: (f, a) => f(...a)
2291
2439
  });
2440
+ await this.networkManager.open();
2292
2441
  await this.spaceManager.open();
2293
2442
  await this.identityManager.open();
2294
2443
  if (this.identityManager.identity) {
@@ -2296,7 +2445,7 @@ var ServiceContext = class {
2296
2445
  }
2297
2446
  (0, import_log10.log)("opened", {}, {
2298
2447
  file: "service-context.ts",
2299
- line: 87,
2448
+ line: 92,
2300
2449
  scope: this,
2301
2450
  callSite: (f, a) => f(...a)
2302
2451
  });
@@ -2305,7 +2454,7 @@ var ServiceContext = class {
2305
2454
  var _a;
2306
2455
  (0, import_log10.log)("closing...", {}, {
2307
2456
  file: "service-context.ts",
2308
- line: 91,
2457
+ line: 96,
2309
2458
  scope: this,
2310
2459
  callSite: (f, a) => f(...a)
2311
2460
  });
@@ -2317,7 +2466,7 @@ var ServiceContext = class {
2317
2466
  this.dataServiceSubscriptions.clear();
2318
2467
  (0, import_log10.log)("closed", {}, {
2319
2468
  file: "service-context.ts",
2320
- line: 98,
2469
+ line: 103,
2321
2470
  scope: this,
2322
2471
  callSite: (f, a) => f(...a)
2323
2472
  });
@@ -2325,7 +2474,7 @@ var ServiceContext = class {
2325
2474
  async reset() {
2326
2475
  (0, import_log10.log)("resetting...", {}, {
2327
2476
  file: "service-context.ts",
2328
- line: 102,
2477
+ line: 107,
2329
2478
  scope: this,
2330
2479
  callSite: (f, a) => f(...a)
2331
2480
  });
@@ -2333,7 +2482,7 @@ var ServiceContext = class {
2333
2482
  await this.storage.reset();
2334
2483
  (0, import_log10.log)("reset", {}, {
2335
2484
  file: "service-context.ts",
2336
- line: 105,
2485
+ line: 110,
2337
2486
  scope: this,
2338
2487
  callSite: (f, a) => f(...a)
2339
2488
  });
@@ -2343,18 +2492,25 @@ var ServiceContext = class {
2343
2492
  await this._initialize();
2344
2493
  return identity;
2345
2494
  }
2495
+ // Called when identity is created.
2346
2496
  async _initialize() {
2347
2497
  var _a;
2498
+ (0, import_log10.log)("initializing spaces...", {}, {
2499
+ file: "service-context.ts",
2500
+ line: 122,
2501
+ scope: this,
2502
+ callSite: (f, a) => f(...a)
2503
+ });
2348
2504
  const identity = (_a = this.identityManager.identity) != null ? _a : (0, import_debug4.failUndefined)();
2349
2505
  const signingContext = {
2350
- credentialProvider: import_echo_db4.MOCK_AUTH_PROVIDER,
2351
- credentialAuthenticator: import_echo_db4.MOCK_AUTH_VERIFIER,
2506
+ credentialProvider: import_echo_db3.MOCK_AUTH_PROVIDER,
2507
+ credentialAuthenticator: import_echo_db3.MOCK_AUTH_VERIFIER,
2352
2508
  credentialSigner: identity.getIdentityCredentialSigner(),
2353
2509
  identityKey: identity.identityKey,
2354
2510
  deviceKey: identity.deviceKey,
2355
2511
  profile: identity.profileDocument
2356
2512
  };
2357
- this.dataSpaceManager = new DataSpaceManager(this.spaceManager, this.metadataStore, this.dataServiceSubscriptions, this.keyring, signingContext, this.modelFactory);
2513
+ this.dataSpaceManager = new DataSpaceManager(this.spaceManager, this.metadataStore, this.dataServiceSubscriptions, this.keyring, signingContext, this.modelFactory, this.snapshotStore);
2358
2514
  await this.dataSpaceManager.open();
2359
2515
  this.spaceInvitations = new SpaceInvitationsHandler(this.networkManager, this.dataSpaceManager, signingContext, this.keyring);
2360
2516
  this.initialized.wake();
@@ -2369,6 +2525,8 @@ var clientServiceBundle = (0, import_rpc.createServiceBundle)({
2369
2525
  DevicesService: import_protocols5.schema.getService("dxos.client.services.DevicesService"),
2370
2526
  SpaceInvitationsService: import_protocols5.schema.getService("dxos.client.services.SpaceInvitationsService"),
2371
2527
  SpacesService: import_protocols5.schema.getService("dxos.client.services.SpacesService"),
2528
+ NetworkService: import_protocols5.schema.getService("dxos.client.services.NetworkService"),
2529
+ // TODO(burdon): Deprecated.
2372
2530
  SpaceService: import_protocols5.schema.getService("dxos.client.SpaceService"),
2373
2531
  DataService: import_protocols5.schema.getService("dxos.echo.service.DataService"),
2374
2532
  ProfileService: import_protocols5.schema.getService("dxos.client.ProfileService"),
@@ -2378,7 +2536,7 @@ var clientServiceBundle = (0, import_rpc.createServiceBundle)({
2378
2536
  });
2379
2537
 
2380
2538
  // packages/sdk/client-services/src/packlets/services/service-host.ts
2381
- var import_debug5 = require("@dxos/debug");
2539
+ var import_debug6 = require("@dxos/debug");
2382
2540
  var import_echo_db5 = require("@dxos/echo-db");
2383
2541
  var import_log11 = require("@dxos/log");
2384
2542
  var import_model_factory = require("@dxos/model-factory");
@@ -2386,7 +2544,7 @@ var import_object_model = require("@dxos/object-model");
2386
2544
  var import_text_model = require("@dxos/text-model");
2387
2545
 
2388
2546
  // packages/sdk/client-services/src/packlets/identity/devices-service-impl.ts
2389
- var import_async13 = require("@dxos/async");
2547
+ var import_async14 = require("@dxos/async");
2390
2548
  var import_codec_protobuf9 = require("@dxos/codec-protobuf");
2391
2549
  var DevicesServiceImpl = class {
2392
2550
  constructor(_identityManager) {
@@ -2412,7 +2570,7 @@ var DevicesServiceImpl = class {
2412
2570
  });
2413
2571
  }
2414
2572
  };
2415
- const dispose = new import_async13.EventSubscriptions();
2573
+ const dispose = new import_async14.EventSubscriptions();
2416
2574
  dispose.add(this._identityManager.stateUpdate.on(() => {
2417
2575
  update();
2418
2576
  if (this._identityManager.identity) {
@@ -2427,8 +2585,37 @@ var DevicesServiceImpl = class {
2427
2585
  }
2428
2586
  };
2429
2587
 
2588
+ // packages/sdk/client-services/src/packlets/network/network-service.ts
2589
+ var import_codec_protobuf10 = require("@dxos/codec-protobuf");
2590
+ var NetworkServiceImpl = class {
2591
+ constructor(networkManager) {
2592
+ this.networkManager = networkManager;
2593
+ }
2594
+ subscribeToNetworkStatus() {
2595
+ return new import_codec_protobuf10.Stream(({ next }) => {
2596
+ const unsubscribe = this.networkManager.connectionStateChanged.on((state) => next({
2597
+ state
2598
+ }));
2599
+ next({
2600
+ state: this.networkManager.connectionState
2601
+ });
2602
+ return unsubscribe;
2603
+ });
2604
+ }
2605
+ async setNetworkOptions(request) {
2606
+ await this.networkManager.setConnectionState(request.state);
2607
+ }
2608
+ };
2609
+
2430
2610
  // packages/sdk/client-services/src/packlets/spaces/spaces-service.ts
2611
+ var import_async15 = require("@dxos/async");
2612
+ var import_codec_protobuf11 = require("@dxos/codec-protobuf");
2613
+ var import_debug5 = require("@dxos/debug");
2614
+ var import_echo_db4 = require("@dxos/echo-db");
2431
2615
  var SpacesServiceImpl = class {
2616
+ constructor(_spaceManager) {
2617
+ this._spaceManager = _spaceManager;
2618
+ }
2432
2619
  async createSpace() {
2433
2620
  throw new Error();
2434
2621
  }
@@ -2438,16 +2625,25 @@ var SpacesServiceImpl = class {
2438
2625
  queryMembers(query) {
2439
2626
  throw new Error();
2440
2627
  }
2628
+ queryCredentials({ spaceKey }) {
2629
+ return new import_codec_protobuf11.Stream(({ ctx, next }) => {
2630
+ var _a;
2631
+ const space = (_a = this._spaceManager.spaces.get(spaceKey)) != null ? _a : (0, import_debug5.raise)(new import_echo_db4.SpaceNotFoundError(spaceKey));
2632
+ const processor = space.spaceState.registerProcessor({
2633
+ process: async (credential) => {
2634
+ next(credential);
2635
+ }
2636
+ });
2637
+ ctx.onDispose(() => processor.close());
2638
+ (0, import_async15.scheduleTask)(ctx, () => processor.open());
2639
+ });
2640
+ }
2441
2641
  };
2442
2642
 
2443
2643
  // packages/sdk/client-services/src/packlets/storage/storage.ts
2444
- var import_jsondown = __toESM(require("jsondown"));
2445
- var import_level_js = __toESM(require("level-js"));
2446
- var import_memdown = __toESM(require("memdown"));
2447
2644
  var import_errors = require("@dxos/errors");
2448
2645
  var import_config = require("@dxos/protocols/proto/dxos/config");
2449
2646
  var import_random_access_storage = require("@dxos/random-access-storage");
2450
- var import_util5 = require("@dxos/util");
2451
2647
  var StorageDriver = import_config.Runtime.Client.Storage.StorageDriver;
2452
2648
  var createStorageObjects = (config) => {
2453
2649
  const { path = "dxos/storage", storageType, keyStorage, persistent = false } = config != null ? config : {};
@@ -2467,23 +2663,9 @@ var createStorageObjects = (config) => {
2467
2663
  storage: (0, import_random_access_storage.createStorage)({
2468
2664
  type: persistent ? toStorageType(storageType) : import_random_access_storage.StorageType.RAM,
2469
2665
  root: `${path}/`
2470
- }),
2471
- keyStorage: createKeyStorage(`${path}/keystore`, persistent ? toKeyStorageType(keyStorage) : "ram")
2666
+ })
2472
2667
  };
2473
2668
  };
2474
- var createKeyStorage = (path, type) => {
2475
- const defaultedType = type != null ? type : (0, import_util5.isNode)() ? "jsondown" : "leveljs";
2476
- switch (defaultedType) {
2477
- case "leveljs":
2478
- return (0, import_level_js.default)(path);
2479
- case "jsondown":
2480
- return (0, import_jsondown.default)(path);
2481
- case "ram":
2482
- return (0, import_memdown.default)();
2483
- default:
2484
- throw new import_errors.InvalidConfigError(`Invalid key storage type: ${defaultedType}`);
2485
- }
2486
- };
2487
2669
  var toStorageType = (type) => {
2488
2670
  switch (type) {
2489
2671
  case void 0:
@@ -2502,23 +2684,10 @@ var toStorageType = (type) => {
2502
2684
  throw new Error(`Invalid storage type: ${StorageDriver[type]}`);
2503
2685
  }
2504
2686
  };
2505
- var toKeyStorageType = (type) => {
2506
- switch (type) {
2507
- case void 0:
2508
- return void 0;
2509
- case StorageDriver.RAM:
2510
- return "ram";
2511
- case StorageDriver.LEVELJS:
2512
- return "leveljs";
2513
- case StorageDriver.JSONDOWN:
2514
- return "jsondown";
2515
- default:
2516
- throw new Error(`Invalid key storage type: ${StorageDriver[type]}`);
2517
- }
2518
- };
2519
2687
 
2520
2688
  // packages/sdk/client-services/src/packlets/services/service-registry.ts
2521
2689
  var ServiceRegistry = class {
2690
+ // prettier-ignore
2522
2691
  constructor(_serviceBundle, _handlers) {
2523
2692
  this._serviceBundle = _serviceBundle;
2524
2693
  this._handlers = _handlers;
@@ -2539,11 +2708,14 @@ var ClientServicesHost = class {
2539
2708
  constructor({
2540
2709
  config,
2541
2710
  modelFactory = createDefaultModelFactory(),
2542
- networkManager
2711
+ // TODO(burdon): Create ApolloLink abstraction (see Client).
2712
+ networkManager,
2713
+ storage = createStorageObjects(config.get("runtime.client.storage", {})).storage
2543
2714
  }) {
2544
2715
  this._config = config;
2545
2716
  this._modelFactory = modelFactory;
2546
2717
  this._networkManager = networkManager;
2718
+ this._storage = storage;
2547
2719
  }
2548
2720
  get descriptors() {
2549
2721
  return this._serviceRegistry.descriptors;
@@ -2553,23 +2725,20 @@ var ClientServicesHost = class {
2553
2725
  }
2554
2726
  async open() {
2555
2727
  var _a;
2556
- await this._initialize();
2557
- const deviceKey = (_a = this._serviceContext.identityManager.identity) == null ? void 0 : _a.deviceKey;
2558
- (0, import_log11.log)("opening...", {
2559
- deviceKey
2560
- }, {
2728
+ (0, import_log11.log)("opening...", {}, {
2561
2729
  file: "service-host.ts",
2562
- line: 69,
2730
+ line: 73,
2563
2731
  scope: this,
2564
2732
  callSite: (f, a) => f(...a)
2565
2733
  });
2566
2734
  await this._initialize();
2567
2735
  await this._serviceContext.open();
2736
+ const deviceKey = (_a = this._serviceContext.identityManager.identity) == null ? void 0 : _a.deviceKey;
2568
2737
  (0, import_log11.log)("opened", {
2569
2738
  deviceKey
2570
2739
  }, {
2571
2740
  file: "service-host.ts",
2572
- line: 72,
2741
+ line: 77,
2573
2742
  scope: this,
2574
2743
  callSite: (f, a) => f(...a)
2575
2744
  });
@@ -2581,7 +2750,7 @@ var ClientServicesHost = class {
2581
2750
  deviceKey
2582
2751
  }, {
2583
2752
  file: "service-host.ts",
2584
- line: 77,
2753
+ line: 82,
2585
2754
  scope: this,
2586
2755
  callSite: (f, a) => f(...a)
2587
2756
  });
@@ -2590,26 +2759,28 @@ var ClientServicesHost = class {
2590
2759
  deviceKey
2591
2760
  }, {
2592
2761
  file: "service-host.ts",
2593
- line: 79,
2762
+ line: 84,
2594
2763
  scope: this,
2595
2764
  callSite: (f, a) => f(...a)
2596
2765
  });
2597
2766
  }
2767
+ // TODO(burdon): Move into open.
2598
2768
  async _initialize() {
2599
- const { storage } = createStorageObjects(this._config.get("runtime.client.storage", {}));
2600
- this._serviceContext = new ServiceContext(storage, this._networkManager, this._modelFactory);
2769
+ this._serviceContext = new ServiceContext(this._storage, this._networkManager, this._modelFactory);
2601
2770
  this._serviceRegistry = new ServiceRegistry(clientServiceBundle, {
2602
2771
  HaloInvitationsService: new HaloInvitationsServiceImpl(this._serviceContext.identityManager, this._serviceContext.haloInvitations),
2603
2772
  DevicesService: new DevicesServiceImpl(this._serviceContext.identityManager),
2604
2773
  SpaceInvitationsService: new SpaceInvitationsServiceImpl(this._serviceContext.identityManager, () => {
2605
2774
  var _a;
2606
- return (_a = this._serviceContext.spaceInvitations) != null ? _a : (0, import_debug5.raise)(new Error("SpaceInvitations not initialized"));
2775
+ return (_a = this._serviceContext.spaceInvitations) != null ? _a : (0, import_debug6.raise)(new Error("SpaceInvitations not initialized"));
2607
2776
  }, () => {
2608
2777
  var _a;
2609
- return (_a = this._serviceContext.dataSpaceManager) != null ? _a : (0, import_debug5.raise)(new Error("SpaceManager not initialized"));
2778
+ return (_a = this._serviceContext.dataSpaceManager) != null ? _a : (0, import_debug6.raise)(new Error("SpaceManager not initialized"));
2610
2779
  }),
2611
- SpacesService: new SpacesServiceImpl(),
2780
+ SpacesService: new SpacesServiceImpl(this._serviceContext.spaceManager),
2612
2781
  DataService: new import_echo_db5.DataServiceImpl(this._serviceContext.dataServiceSubscriptions),
2782
+ NetworkService: new NetworkServiceImpl(this._serviceContext.networkManager),
2783
+ // TODO(burdon): Move to new protobuf definitions.
2613
2784
  ProfileService: new ProfileServiceImpl(this._serviceContext),
2614
2785
  SpaceService: new SpaceServiceImpl(this._serviceContext),
2615
2786
  SystemService: new SystemServiceImpl(this._config, this._serviceContext),
@@ -2624,10 +2795,11 @@ var ClientServicesHost = class {
2624
2795
  };
2625
2796
 
2626
2797
  // packages/sdk/client-services/src/packlets/services/service-proxy.ts
2627
- var import_async14 = require("@dxos/async");
2798
+ var import_async16 = require("@dxos/async");
2628
2799
  var import_errors2 = require("@dxos/errors");
2629
2800
  var import_rpc2 = require("@dxos/rpc");
2630
2801
  var ClientServicesProxy = class {
2802
+ // prettier-ignore
2631
2803
  constructor(port, _timeout = 3e4) {
2632
2804
  this._timeout = _timeout;
2633
2805
  this._proxy = (0, import_rpc2.createProtoRpcPeer)({
@@ -2647,7 +2819,7 @@ var ClientServicesProxy = class {
2647
2819
  return this._proxy.rpc;
2648
2820
  }
2649
2821
  async open() {
2650
- await (0, import_async14.asyncTimeout)(this._proxy.open(), this._timeout, new import_errors2.RemoteServiceConnectionTimeout());
2822
+ await (0, import_async16.asyncTimeout)(this._proxy.open(), this._timeout, new import_errors2.RemoteServiceConnectionTimeout());
2651
2823
  }
2652
2824
  async close() {
2653
2825
  await this._proxy.close();
@@ -2704,17 +2876,17 @@ var IFrameRuntime = class {
2704
2876
  };
2705
2877
 
2706
2878
  // packages/sdk/client-services/src/packlets/vault/worker-runtime.ts
2707
- var import_async16 = require("@dxos/async");
2879
+ var import_async18 = require("@dxos/async");
2708
2880
  var import_messaging = require("@dxos/messaging");
2709
2881
  var import_network_manager4 = require("@dxos/network-manager");
2710
2882
 
2711
2883
  // packages/sdk/client-services/src/packlets/vault/worker-session.ts
2712
2884
  var import_node_assert11 = __toESM(require("node:assert"));
2713
- var import_async15 = require("@dxos/async");
2885
+ var import_async17 = require("@dxos/async");
2714
2886
  var import_log12 = require("@dxos/log");
2715
2887
  var import_rpc4 = require("@dxos/rpc");
2716
- var import_util6 = require("@dxos/util");
2717
- var __decorate2 = function(decorators, target, key, desc) {
2888
+ var import_util5 = require("@dxos/util");
2889
+ var __decorate3 = function(decorators, target, key, desc) {
2718
2890
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2719
2891
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
2720
2892
  r = Reflect.decorate(decorators, target, key, desc);
@@ -2728,8 +2900,8 @@ var WorkerSession = class {
2728
2900
  constructor({ getServices, systemPort, appPort, options = {
2729
2901
  heartbeatInterval: 1e3
2730
2902
  } }) {
2731
- this._startTrigger = new import_async15.Trigger();
2732
- this.onClose = new import_util6.Callback();
2903
+ this._startTrigger = new import_async17.Trigger();
2904
+ this.onClose = new import_util5.Callback();
2733
2905
  (0, import_node_assert11.default)(options);
2734
2906
  (0, import_node_assert11.default)(getServices);
2735
2907
  this._options = options;
@@ -2741,6 +2913,7 @@ var WorkerSession = class {
2741
2913
  DevicesService: async () => (await this._getServices()).services.DevicesService,
2742
2914
  SpaceInvitationsService: async () => (await this._getServices()).services.SpaceInvitationsService,
2743
2915
  SpacesService: async () => (await this._getServices()).services.SpacesService,
2916
+ NetworkService: async () => (await this._getServices()).services.NetworkService,
2744
2917
  SpaceService: async () => (await this._getServices()).services.SpaceService,
2745
2918
  DataService: async () => (await this._getServices()).services.DataService,
2746
2919
  ProfileService: async () => (await this._getServices()).services.ProfileService,
@@ -2766,7 +2939,7 @@ var WorkerSession = class {
2766
2939
  } catch (err) {
2767
2940
  import_log12.log.catch(err, {}, {
2768
2941
  file: "worker-session.ts",
2769
- line: 89,
2942
+ line: 90,
2770
2943
  scope: this,
2771
2944
  callSite: (f, a) => f(...a)
2772
2945
  });
@@ -2777,13 +2950,14 @@ var WorkerSession = class {
2777
2950
  },
2778
2951
  port: systemPort,
2779
2952
  timeout: 1e3
2953
+ // With low timeout heartbeat may fail if the tab's thread is saturated.
2780
2954
  });
2781
2955
  this.bridgeService = this._iframeRpc.rpc.BridgeService;
2782
2956
  }
2783
2957
  async open() {
2784
2958
  import_log12.log.info("opening..", {}, {
2785
2959
  file: "worker-session.ts",
2786
- line: 103,
2960
+ line: 104,
2787
2961
  scope: this,
2788
2962
  callSite: (f, a) => f(...a)
2789
2963
  });
@@ -2802,7 +2976,7 @@ var WorkerSession = class {
2802
2976
  err: err1
2803
2977
  }, {
2804
2978
  file: "worker-session.ts",
2805
- line: 115,
2979
+ line: 116,
2806
2980
  scope: this,
2807
2981
  callSite: (f, a) => f(...a)
2808
2982
  });
@@ -2811,7 +2985,7 @@ var WorkerSession = class {
2811
2985
  } catch (err) {
2812
2986
  import_log12.log.catch(err, {}, {
2813
2987
  file: "worker-session.ts",
2814
- line: 119,
2988
+ line: 120,
2815
2989
  scope: this,
2816
2990
  callSite: (f, a) => f(...a)
2817
2991
  });
@@ -2822,7 +2996,7 @@ var WorkerSession = class {
2822
2996
  async close() {
2823
2997
  import_log12.log.info("closing..", {}, {
2824
2998
  file: "worker-session.ts",
2825
- line: 126,
2999
+ line: 127,
2826
3000
  scope: this,
2827
3001
  callSite: (f, a) => f(...a)
2828
3002
  });
@@ -2831,7 +3005,7 @@ var WorkerSession = class {
2831
3005
  } catch (err) {
2832
3006
  import_log12.log.catch(err, {}, {
2833
3007
  file: "worker-session.ts",
2834
- line: 130,
3008
+ line: 131,
2835
3009
  scope: this,
2836
3010
  callSite: (f, a) => f(...a)
2837
3011
  });
@@ -2845,16 +3019,17 @@ var WorkerSession = class {
2845
3019
  ]);
2846
3020
  }
2847
3021
  };
2848
- __decorate2([
3022
+ __decorate3([
2849
3023
  import_log12.logInfo
2850
3024
  ], WorkerSession.prototype, "origin", void 0);
2851
3025
 
2852
3026
  // packages/sdk/client-services/src/packlets/vault/worker-runtime.ts
2853
3027
  var WorkerRuntime = class {
3028
+ // prettier-ignore
2854
3029
  constructor(_configProvider) {
2855
3030
  this._configProvider = _configProvider;
2856
3031
  this._transportFactory = new import_network_manager4.WebRTCTransportProxyFactory();
2857
- this._ready = new import_async16.Trigger();
3032
+ this._ready = new import_async18.Trigger();
2858
3033
  this.sessions = /* @__PURE__ */ new Set();
2859
3034
  }
2860
3035
  async start() {
@@ -2880,6 +3055,9 @@ var WorkerRuntime = class {
2880
3055
  async stop() {
2881
3056
  await this._clientServices.close();
2882
3057
  }
3058
+ /**
3059
+ * Create a new session.
3060
+ */
2883
3061
  async createSession({ appPort, systemPort }) {
2884
3062
  const session = new WorkerSession({
2885
3063
  getServices: async () => {
@@ -2901,6 +3079,9 @@ var WorkerRuntime = class {
2901
3079
  this.sessions.add(session);
2902
3080
  this._reconnectWebrtc();
2903
3081
  }
3082
+ /**
3083
+ * Selects one of the existing session fro WebRTC networking.
3084
+ */
2904
3085
  _reconnectWebrtc() {
2905
3086
  if (this._sessionForNetworking) {
2906
3087
  if (!this.sessions.has(this._sessionForNetworking)) {