@dxos/client-services 0.1.31-next.ea8f0bc → 0.1.32-next.77d513e

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 (57) hide show
  1. package/dist/lib/browser/{chunk-ZIQUYEJS.mjs → chunk-E3FD43YN.mjs} +460 -213
  2. package/dist/lib/browser/chunk-E3FD43YN.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +1 -1
  4. package/dist/lib/browser/meta.json +1 -1
  5. package/dist/lib/browser/packlets/testing/index.mjs +64 -6
  6. package/dist/lib/browser/packlets/testing/index.mjs.map +3 -3
  7. package/dist/lib/node/index.cjs +462 -215
  8. package/dist/lib/node/index.cjs.map +3 -3
  9. package/dist/lib/node/meta.json +1 -1
  10. package/dist/lib/node/packlets/testing/index.cjs +524 -218
  11. package/dist/lib/node/packlets/testing/index.cjs.map +3 -3
  12. package/dist/types/src/packlets/identity/identity-manager.d.ts +6 -0
  13. package/dist/types/src/packlets/identity/identity-manager.d.ts.map +1 -1
  14. package/dist/types/src/packlets/invitations/device-invitations-handler.d.ts.map +1 -1
  15. package/dist/types/src/packlets/invitations/space-invitations-handler.d.ts.map +1 -1
  16. package/dist/types/src/packlets/services/service-host.d.ts +1 -0
  17. package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
  18. package/dist/types/src/packlets/spaces/data-space-manager.d.ts +19 -1
  19. package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
  20. package/dist/types/src/packlets/spaces/data-space.d.ts +32 -5
  21. package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
  22. package/dist/types/src/packlets/spaces/notarization-plugin.d.ts +29 -1
  23. package/dist/types/src/packlets/spaces/notarization-plugin.d.ts.map +1 -1
  24. package/dist/types/src/packlets/spaces/spaces-service.d.ts +4 -1
  25. package/dist/types/src/packlets/spaces/spaces-service.d.ts.map +1 -1
  26. package/dist/types/src/packlets/testing/host-test-builder.d.ts +2 -2
  27. package/dist/types/src/packlets/testing/host-test-builder.d.ts.map +1 -1
  28. package/dist/types/src/packlets/testing/test-builder.d.ts +2 -0
  29. package/dist/types/src/packlets/testing/test-builder.d.ts.map +1 -1
  30. package/dist/types/src/packlets/tests/text.test.d.ts +2 -0
  31. package/dist/types/src/packlets/tests/text.test.d.ts.map +1 -0
  32. package/dist/types/src/packlets/vault/vault-resource-lock.d.ts +1 -0
  33. package/dist/types/src/packlets/vault/vault-resource-lock.d.ts.map +1 -1
  34. package/package.json +31 -30
  35. package/src/packlets/identity/identity-manager.ts +32 -17
  36. package/src/packlets/invitations/device-invitations-handler.ts +5 -3
  37. package/src/packlets/invitations/space-invitations-handler.test.ts +20 -3
  38. package/src/packlets/invitations/space-invitations-handler.ts +15 -8
  39. package/src/packlets/services/service-context.test.ts +6 -5
  40. package/src/packlets/services/service-host.ts +7 -2
  41. package/src/packlets/spaces/data-space-manager.test.ts +77 -2
  42. package/src/packlets/spaces/data-space-manager.ts +87 -37
  43. package/src/packlets/spaces/data-space.ts +103 -16
  44. package/src/packlets/spaces/notarization-plugin.test.ts +3 -1
  45. package/src/packlets/spaces/notarization-plugin.ts +67 -19
  46. package/src/packlets/spaces/spaces-service.test.ts +1 -1
  47. package/src/packlets/spaces/spaces-service.ts +53 -17
  48. package/src/packlets/testing/host-test-builder.ts +2 -2
  49. package/src/packlets/testing/test-builder.ts +45 -5
  50. package/src/packlets/tests/client-services.test.ts +24 -11
  51. package/src/packlets/tests/client.test.ts +3 -6
  52. package/src/packlets/tests/halo-profile.test.ts +5 -5
  53. package/src/packlets/tests/spaces-invitations.test.ts +47 -7
  54. package/src/packlets/tests/spaces.test.ts +86 -9
  55. package/src/packlets/tests/text.test.ts +206 -0
  56. package/src/packlets/vault/vault-resource-lock.ts +10 -1
  57. package/dist/lib/browser/chunk-ZIQUYEJS.mjs.map +0 -7
@@ -39,6 +39,7 @@ __export(testing_exports, {
39
39
  createServiceContext: () => createServiceContext,
40
40
  createServiceHost: () => createServiceHost,
41
41
  createSigningContext: () => createSigningContext,
42
+ joinCommonSpace: () => joinCommonSpace,
42
43
  performInvitation: () => performInvitation,
43
44
  syncItems: () => syncItems,
44
45
  syncItemsLocal: () => syncItemsLocal,
@@ -64,7 +65,7 @@ var createMockCredential = async ({ signer, issuer }) => (0, import_credentials.
64
65
  });
65
66
 
66
67
  // packages/sdk/client-services/src/packlets/testing/host-test-builder.ts
67
- var import_client7 = require("@dxos/client");
68
+ var import_client9 = require("@dxos/client");
68
69
  var import_credentials13 = require("@dxos/credentials");
69
70
  var import_echo_pipeline6 = require("@dxos/echo-pipeline");
70
71
  var import_testing = require("@dxos/echo-pipeline/testing");
@@ -77,10 +78,10 @@ var import_random_access_storage2 = require("@dxos/random-access-storage");
77
78
  // packages/sdk/client-services/src/packlets/services/service-host.ts
78
79
  var import_node_assert12 = __toESM(require("node:assert"));
79
80
  var import_async19 = require("@dxos/async");
80
- var import_client6 = require("@dxos/client");
81
+ var import_client8 = require("@dxos/client");
81
82
  var import_debug7 = require("@dxos/debug");
82
83
  var import_echo_pipeline5 = require("@dxos/echo-pipeline");
83
- var import_log15 = require("@dxos/log");
84
+ var import_log16 = require("@dxos/log");
84
85
  var import_services8 = require("@dxos/protocols/proto/dxos/client/services");
85
86
 
86
87
  // packages/sdk/client-services/src/packlets/deprecated/tracing.ts
@@ -697,7 +698,7 @@ var IdentityManager = class {
697
698
  identityRecord
698
699
  }, {
699
700
  file: "identity-manager.ts",
700
- line: 63,
701
+ line: 71,
701
702
  scope: this,
702
703
  callSite: (f, a) => f(...a)
703
704
  });
@@ -716,7 +717,7 @@ var IdentityManager = class {
716
717
  (0, import_node_assert2.default)(!this._identity, "Identity already exists.");
717
718
  (0, import_log3.log)("creating identity...", {}, {
718
719
  file: "identity-manager.ts",
719
- line: 78,
720
+ line: 86,
720
721
  scope: this,
721
722
  callSite: (f, a) => f(...a)
722
723
  });
@@ -725,21 +726,23 @@ var IdentityManager = class {
725
726
  identityKey: await this._keyring.createKey(),
726
727
  deviceKey: await this._keyring.createKey(),
727
728
  haloSpace: {
728
- spaceKey: await this._keyring.createKey(),
729
+ key: await this._keyring.createKey(),
729
730
  genesisFeedKey: controlFeedKey,
730
- writeControlFeedKey: controlFeedKey,
731
- writeDataFeedKey: await this._keyring.createKey()
731
+ controlFeedKey,
732
+ dataFeedKey: await this._keyring.createKey()
732
733
  }
733
734
  };
734
735
  const identity = await this._constructIdentity(identityRecord);
735
736
  await identity.open();
736
737
  {
737
738
  const generator = new import_credentials5.CredentialGenerator(this._keyring, identityRecord.identityKey, identityRecord.deviceKey);
739
+ (0, import_node_assert2.default)(identityRecord.haloSpace.genesisFeedKey, "Genesis feed key is required.");
740
+ (0, import_node_assert2.default)(identityRecord.haloSpace.dataFeedKey, "Data feed key is required.");
738
741
  const credentials = [
739
742
  // Space genesis.
740
- ...await generator.createSpaceGenesis(identityRecord.haloSpace.spaceKey, identityRecord.haloSpace.genesisFeedKey),
743
+ ...await generator.createSpaceGenesis(identityRecord.haloSpace.key, identityRecord.haloSpace.genesisFeedKey),
741
744
  // Feed admission.
742
- await generator.createFeedAdmission(identityRecord.haloSpace.spaceKey, identityRecord.haloSpace.writeDataFeedKey, import_credentials6.AdmittedFeed.Designation.DATA)
745
+ await generator.createFeedAdmission(identityRecord.haloSpace.key, identityRecord.haloSpace.dataFeedKey, import_credentials6.AdmittedFeed.Designation.DATA)
743
746
  ];
744
747
  if (displayName) {
745
748
  credentials.push(await generator.createProfileCredential({
@@ -764,7 +767,7 @@ var IdentityManager = class {
764
767
  deviceKey: identity.deviceKey
765
768
  }, {
766
769
  file: "identity-manager.ts",
767
- line: 136,
770
+ line: 143,
768
771
  scope: this,
769
772
  callSite: (f, a) => f(...a)
770
773
  });
@@ -778,7 +781,7 @@ var IdentityManager = class {
778
781
  params
779
782
  }, {
780
783
  file: "identity-manager.ts",
781
- line: 144,
784
+ line: 151,
782
785
  scope: this,
783
786
  callSite: (f, a) => f(...a)
784
787
  });
@@ -787,10 +790,11 @@ var IdentityManager = class {
787
790
  identityKey: params.identityKey,
788
791
  deviceKey: params.deviceKey,
789
792
  haloSpace: {
790
- spaceKey: params.haloSpaceKey,
793
+ key: params.haloSpaceKey,
791
794
  genesisFeedKey: params.haloGenesisFeedKey,
792
- writeControlFeedKey: params.controlFeedKey,
793
- writeDataFeedKey: params.dataFeedKey
795
+ controlFeedKey: params.controlFeedKey,
796
+ dataFeedKey: params.dataFeedKey,
797
+ controlTimeframe: params.controlTimeframe
794
798
  }
795
799
  };
796
800
  const identity = await this._constructIdentity(identityRecord);
@@ -804,7 +808,7 @@ var IdentityManager = class {
804
808
  deviceKey: identity.deviceKey
805
809
  }, {
806
810
  file: "identity-manager.ts",
807
- line: 164,
811
+ line: 172,
808
812
  scope: this,
809
813
  callSite: (f, a) => f(...a)
810
814
  });
@@ -816,14 +820,16 @@ var IdentityManager = class {
816
820
  identityRecord
817
821
  }, {
818
822
  file: "identity-manager.ts",
819
- line: 170,
823
+ line: 178,
820
824
  scope: this,
821
825
  callSite: (f, a) => f(...a)
822
826
  });
823
- const controlFeed = await this._feedStore.openFeed(identityRecord.haloSpace.writeControlFeedKey, {
827
+ (0, import_node_assert2.default)(identityRecord.haloSpace.controlFeedKey);
828
+ const controlFeed = await this._feedStore.openFeed(identityRecord.haloSpace.controlFeedKey, {
824
829
  writable: true
825
830
  });
826
- const dataFeed = await this._feedStore.openFeed(identityRecord.haloSpace.writeDataFeedKey, {
831
+ (0, import_node_assert2.default)(identityRecord.haloSpace.dataFeedKey);
832
+ const dataFeed = await this._feedStore.openFeed(identityRecord.haloSpace.dataFeedKey, {
827
833
  writable: true
828
834
  });
829
835
  const space = await this._constructSpace({
@@ -847,16 +853,19 @@ var IdentityManager = class {
847
853
  identityKey: identityRecord.identityKey
848
854
  }, {
849
855
  file: "identity-manager.ts",
850
- line: 196,
856
+ line: 206,
851
857
  scope: this,
852
858
  callSite: (f, a) => f(...a)
853
859
  });
860
+ if (identityRecord.haloSpace.controlTimeframe) {
861
+ identity.controlPipeline.state.setTargetTimeframe(identityRecord.haloSpace.controlTimeframe);
862
+ }
854
863
  return identity;
855
864
  }
856
865
  async _constructSpace({ spaceRecord, swarmIdentity, identityKey }) {
857
866
  return this._spaceManager.constructSpace({
858
867
  metadata: {
859
- key: spaceRecord.spaceKey,
868
+ key: spaceRecord.key,
860
869
  genesisFeedKey: spaceRecord.genesisFeedKey
861
870
  },
862
871
  swarmIdentity,
@@ -972,7 +981,8 @@ var DeviceInvitationsHandler = class extends import_client.AbstractInvitationsHa
972
981
  return {
973
982
  identityKey: identity.identityKey,
974
983
  haloSpaceKey: identity.haloSpaceKey,
975
- genesisFeedKey: identity.haloGenesisFeedKey
984
+ genesisFeedKey: identity.haloGenesisFeedKey,
985
+ controlTimeframe: identity.controlPipeline.state.timeframe
976
986
  };
977
987
  },
978
988
  authenticate: async ({ authenticationCode: code }) => {
@@ -980,7 +990,7 @@ var DeviceInvitationsHandler = class extends import_client.AbstractInvitationsHa
980
990
  authenticationCode: code
981
991
  }, {
982
992
  file: "device-invitations-handler.ts",
983
- line: 106,
993
+ line: 107,
984
994
  scope: this,
985
995
  callSite: (f, a) => f(...a)
986
996
  });
@@ -1002,7 +1012,7 @@ var DeviceInvitationsHandler = class extends import_client.AbstractInvitationsHa
1002
1012
  guest: credentials.deviceKey
1003
1013
  }, {
1004
1014
  file: "device-invitations-handler.ts",
1005
- line: 121,
1015
+ line: 122,
1006
1016
  scope: this,
1007
1017
  callSite: (f, a) => f(...a)
1008
1018
  });
@@ -1021,7 +1031,7 @@ var DeviceInvitationsHandler = class extends import_client.AbstractInvitationsHa
1021
1031
  host: identity.deviceKey
1022
1032
  }, {
1023
1033
  file: "device-invitations-handler.ts",
1024
- line: 137,
1034
+ line: 138,
1025
1035
  scope: this,
1026
1036
  callSite: (f, a) => f(...a)
1027
1037
  });
@@ -1034,7 +1044,7 @@ var DeviceInvitationsHandler = class extends import_client.AbstractInvitationsHa
1034
1044
  guest: deviceKey
1035
1045
  }, {
1036
1046
  file: "device-invitations-handler.ts",
1037
- line: 140,
1047
+ line: 141,
1038
1048
  scope: this,
1039
1049
  callSite: (f, a) => f(...a)
1040
1050
  });
@@ -1043,7 +1053,7 @@ var DeviceInvitationsHandler = class extends import_client.AbstractInvitationsHa
1043
1053
  if (!observable.cancelled) {
1044
1054
  import_log4.log.error("failed", err, {
1045
1055
  file: "device-invitations-handler.ts",
1046
- line: 144,
1056
+ line: 145,
1047
1057
  scope: this,
1048
1058
  callSite: (f, a) => f(...a)
1049
1059
  });
@@ -1108,22 +1118,22 @@ var DeviceInvitationsHandler = class extends import_client.AbstractInvitationsHa
1108
1118
  }
1109
1119
  (0, import_log4.log)("connected", {}, {
1110
1120
  file: "device-invitations-handler.ts",
1111
- line: 215,
1121
+ line: 216,
1112
1122
  scope: this,
1113
1123
  callSite: (f, a) => f(...a)
1114
1124
  });
1115
1125
  (_b = (_a = observable.callback).onConnected) == null ? void 0 : _b.call(_a, invitation);
1116
1126
  (0, import_log4.log)("sending admission request", {}, {
1117
1127
  file: "device-invitations-handler.ts",
1118
- line: 219,
1128
+ line: 220,
1119
1129
  scope: this,
1120
1130
  callSite: (f, a) => f(...a)
1121
1131
  });
1122
- const { identityKey, haloSpaceKey, genesisFeedKey } = await extension.rpc.HaloHostService.requestAdmission();
1132
+ const { identityKey, haloSpaceKey, genesisFeedKey, controlTimeframe } = await extension.rpc.HaloHostService.requestAdmission();
1123
1133
  if (invitation.type === void 0 || invitation.type === import_services2.Invitation.Type.INTERACTIVE) {
1124
1134
  (0, import_log4.log)("guest waiting for authentication code...", {}, {
1125
1135
  file: "device-invitations-handler.ts",
1126
- line: 226,
1136
+ line: 227,
1127
1137
  scope: this,
1128
1138
  callSite: (f, a) => f(...a)
1129
1139
  });
@@ -1133,7 +1143,7 @@ var DeviceInvitationsHandler = class extends import_client.AbstractInvitationsHa
1133
1143
  });
1134
1144
  (0, import_log4.log)("sending authentication request", {}, {
1135
1145
  file: "device-invitations-handler.ts",
1136
- line: 229,
1146
+ line: 230,
1137
1147
  scope: this,
1138
1148
  callSite: (f, a) => f(...a)
1139
1149
  });
@@ -1151,7 +1161,7 @@ var DeviceInvitationsHandler = class extends import_client.AbstractInvitationsHa
1151
1161
  dataFeedKey
1152
1162
  }, {
1153
1163
  file: "device-invitations-handler.ts",
1154
- line: 238,
1164
+ line: 239,
1155
1165
  scope: this,
1156
1166
  callSite: (f, a) => f(...a)
1157
1167
  });
@@ -1166,14 +1176,15 @@ var DeviceInvitationsHandler = class extends import_client.AbstractInvitationsHa
1166
1176
  haloSpaceKey,
1167
1177
  haloGenesisFeedKey: genesisFeedKey,
1168
1178
  controlFeedKey,
1169
- dataFeedKey
1179
+ dataFeedKey,
1180
+ controlTimeframe
1170
1181
  });
1171
1182
  (0, import_log4.log)("admitted by host", {
1172
1183
  guest: identity.deviceKey,
1173
1184
  identityKey
1174
1185
  }, {
1175
1186
  file: "device-invitations-handler.ts",
1176
- line: 257,
1187
+ line: 259,
1177
1188
  scope: this,
1178
1189
  callSite: (f, a) => f(...a)
1179
1190
  });
@@ -1182,7 +1193,7 @@ var DeviceInvitationsHandler = class extends import_client.AbstractInvitationsHa
1182
1193
  if (!observable.cancelled) {
1183
1194
  import_log4.log.warn("auth failed", err, {
1184
1195
  file: "device-invitations-handler.ts",
1185
- line: 261,
1196
+ line: 263,
1186
1197
  scope: this,
1187
1198
  callSite: (f, a) => f(...a)
1188
1199
  });
@@ -1626,6 +1637,7 @@ var SpaceInvitationsHandler = class extends import_client2.AbstractInvitationsHa
1626
1637
  };
1627
1638
  },
1628
1639
  requestAdmission: async ({ identityKey, deviceKey, controlFeedKey, dataFeedKey }) => {
1640
+ var _a2;
1629
1641
  try {
1630
1642
  if (isAuthenticationRequired(invitation) && !authenticationPassed) {
1631
1643
  throw new Error("Not authenticated");
@@ -1646,7 +1658,9 @@ var SpaceInvitationsHandler = class extends import_client2.AbstractInvitationsHa
1646
1658
  await (0, import_feed_store3.writeMessages)(space.inner.controlPipeline.writer, credentials);
1647
1659
  complete.wake(deviceKey);
1648
1660
  return {
1649
- credential: spaceMemberCredential
1661
+ credential: spaceMemberCredential,
1662
+ controlTimeframe: space.inner.controlPipeline.state.timeframe,
1663
+ dataTimeframe: (_a2 = space.dataPipeline.pipelineState) == null ? void 0 : _a2.timeframe
1650
1664
  };
1651
1665
  } catch (err) {
1652
1666
  observable.callback.onError(err);
@@ -1661,7 +1675,7 @@ var SpaceInvitationsHandler = class extends import_client2.AbstractInvitationsHa
1661
1675
  host: this._signingContext.deviceKey
1662
1676
  }, {
1663
1677
  file: "space-invitations-handler.ts",
1664
- line: 191,
1678
+ line: 195,
1665
1679
  scope: this,
1666
1680
  callSite: (f, a) => f(...a)
1667
1681
  });
@@ -1674,7 +1688,7 @@ var SpaceInvitationsHandler = class extends import_client2.AbstractInvitationsHa
1674
1688
  guest: deviceKey
1675
1689
  }, {
1676
1690
  file: "space-invitations-handler.ts",
1677
- line: 194,
1691
+ line: 198,
1678
1692
  scope: this,
1679
1693
  callSite: (f, a) => f(...a)
1680
1694
  });
@@ -1683,7 +1697,7 @@ var SpaceInvitationsHandler = class extends import_client2.AbstractInvitationsHa
1683
1697
  if (!observable.cancelled) {
1684
1698
  import_log6.log.error("failed", err, {
1685
1699
  file: "space-invitations-handler.ts",
1686
- line: 198,
1700
+ line: 202,
1687
1701
  scope: this,
1688
1702
  callSite: (f, a) => f(...a)
1689
1703
  });
@@ -1753,7 +1767,7 @@ var SpaceInvitationsHandler = class extends import_client2.AbstractInvitationsHa
1753
1767
  guest: this._signingContext.deviceKey
1754
1768
  }, {
1755
1769
  file: "space-invitations-handler.ts",
1756
- line: 271,
1770
+ line: 275,
1757
1771
  scope: this,
1758
1772
  callSite: (f, a) => f(...a)
1759
1773
  });
@@ -1762,7 +1776,7 @@ var SpaceInvitationsHandler = class extends import_client2.AbstractInvitationsHa
1762
1776
  guest: this._signingContext.deviceKey
1763
1777
  }, {
1764
1778
  file: "space-invitations-handler.ts",
1765
- line: 275,
1779
+ line: 279,
1766
1780
  scope: this,
1767
1781
  callSite: (f, a) => f(...a)
1768
1782
  });
@@ -1774,7 +1788,7 @@ var SpaceInvitationsHandler = class extends import_client2.AbstractInvitationsHa
1774
1788
  response: introductionResponse
1775
1789
  }, {
1776
1790
  file: "space-invitations-handler.ts",
1777
- line: 279,
1791
+ line: 283,
1778
1792
  scope: this,
1779
1793
  callSite: (f, a) => f(...a)
1780
1794
  });
@@ -1787,7 +1801,7 @@ var SpaceInvitationsHandler = class extends import_client2.AbstractInvitationsHa
1787
1801
  for (let attempt = 1; attempt <= MAX_OTP_ATTEMPTS; attempt++) {
1788
1802
  (0, import_log6.log)("guest waiting for authentication code...", {}, {
1789
1803
  file: "space-invitations-handler.ts",
1790
- line: 293,
1804
+ line: 297,
1791
1805
  scope: this,
1792
1806
  callSite: (f, a) => f(...a)
1793
1807
  });
@@ -1797,7 +1811,7 @@ var SpaceInvitationsHandler = class extends import_client2.AbstractInvitationsHa
1797
1811
  });
1798
1812
  (0, import_log6.log)("sending authentication request", {}, {
1799
1813
  file: "space-invitations-handler.ts",
1800
- line: 297,
1814
+ line: 301,
1801
1815
  scope: this,
1802
1816
  callSite: (f, a) => f(...a)
1803
1817
  });
@@ -1815,7 +1829,7 @@ var SpaceInvitationsHandler = class extends import_client2.AbstractInvitationsHa
1815
1829
  attempt
1816
1830
  }, {
1817
1831
  file: "space-invitations-handler.ts",
1818
- line: 307,
1832
+ line: 311,
1819
1833
  scope: this,
1820
1834
  callSite: (f, a) => f(...a)
1821
1835
  });
@@ -1830,11 +1844,11 @@ var SpaceInvitationsHandler = class extends import_client2.AbstractInvitationsHa
1830
1844
  guest: this._signingContext.deviceKey
1831
1845
  }, {
1832
1846
  file: "space-invitations-handler.ts",
1833
- line: 318,
1847
+ line: 322,
1834
1848
  scope: this,
1835
1849
  callSite: (f, a) => f(...a)
1836
1850
  });
1837
- const { credential } = await extension.rpc.SpaceHostService.requestAdmission({
1851
+ const { credential, controlTimeframe, dataTimeframe } = await extension.rpc.SpaceHostService.requestAdmission({
1838
1852
  identityKey: this._signingContext.identityKey,
1839
1853
  deviceKey: this._signingContext.deviceKey,
1840
1854
  controlFeedKey,
@@ -1845,7 +1859,9 @@ var SpaceInvitationsHandler = class extends import_client2.AbstractInvitationsHa
1845
1859
  (0, import_node_assert6.default)(credential.subject.id.equals(this._signingContext.identityKey));
1846
1860
  const space = await this._spaceManager.acceptSpace({
1847
1861
  spaceKey: assertion.spaceKey,
1848
- genesisFeedKey: assertion.genesisFeedKey
1862
+ genesisFeedKey: assertion.genesisFeedKey,
1863
+ controlTimeframe,
1864
+ dataTimeframe
1849
1865
  });
1850
1866
  await this._signingContext.recordCredential(credential);
1851
1867
  (0, import_log6.log)("admitted by host", {
@@ -1853,7 +1869,7 @@ var SpaceInvitationsHandler = class extends import_client2.AbstractInvitationsHa
1853
1869
  spaceKey: space.key
1854
1870
  }, {
1855
1871
  file: "space-invitations-handler.ts",
1856
- line: 340,
1872
+ line: 347,
1857
1873
  scope: this,
1858
1874
  callSite: (f, a) => f(...a)
1859
1875
  });
@@ -1862,7 +1878,7 @@ var SpaceInvitationsHandler = class extends import_client2.AbstractInvitationsHa
1862
1878
  if (!observable.cancelled) {
1863
1879
  import_log6.log.warn("auth failed", err, {
1864
1880
  file: "space-invitations-handler.ts",
1865
- line: 344,
1881
+ line: 351,
1866
1882
  scope: this,
1867
1883
  callSite: (f, a) => f(...a)
1868
1884
  });
@@ -1990,20 +2006,24 @@ var NetworkServiceImpl = class {
1990
2006
  // packages/sdk/client-services/src/packlets/spaces/data-space-manager.ts
1991
2007
  var import_node_assert9 = __toESM(require("node:assert"));
1992
2008
  var import_async11 = require("@dxos/async");
2009
+ var import_client4 = require("@dxos/client");
1993
2010
  var import_context7 = require("@dxos/context");
1994
2011
  var import_credentials11 = require("@dxos/credentials");
1995
2012
  var import_echo_pipeline2 = require("@dxos/echo-pipeline");
1996
2013
  var import_keys9 = require("@dxos/keys");
1997
- var import_log8 = require("@dxos/log");
1998
- var import_teleport_extension_presence = require("@dxos/teleport-extension-presence");
2014
+ var import_log9 = require("@dxos/log");
2015
+ var import_teleport_extension_gossip = require("@dxos/teleport-extension-gossip");
1999
2016
  var import_util5 = require("@dxos/util");
2000
2017
 
2001
2018
  // packages/sdk/client-services/src/packlets/spaces/data-space.ts
2002
2019
  var import_async10 = require("@dxos/async");
2020
+ var import_client3 = require("@dxos/client");
2003
2021
  var import_context6 = require("@dxos/context");
2004
2022
  var import_debug3 = require("@dxos/debug");
2005
2023
  var import_echo_pipeline = require("@dxos/echo-pipeline");
2024
+ var import_errors = require("@dxos/errors");
2006
2025
  var import_keys8 = require("@dxos/keys");
2026
+ var import_log8 = require("@dxos/log");
2007
2027
  var import_credentials10 = require("@dxos/protocols/proto/dxos/halo/credentials");
2008
2028
  var import_util4 = require("@dxos/util");
2009
2029
 
@@ -2016,8 +2036,9 @@ var import_log7 = require("@dxos/log");
2016
2036
  var import_protocols4 = require("@dxos/protocols");
2017
2037
  var import_teleport3 = require("@dxos/teleport");
2018
2038
  var import_util3 = require("@dxos/util");
2019
- var RETRY_TIMEOUT = 1e3;
2020
- var NOTARIZE_TIMEOUT = 1e4;
2039
+ var DEFAULT_RETRY_TIMEOUT = 1e3;
2040
+ var DEFAULT_SUCCESS_DELAY = 1e3;
2041
+ var DEFAULT_NOTARIZE_TIMEOUT = 1e4;
2021
2042
  var NotarizationPlugin = class {
2022
2043
  constructor() {
2023
2044
  this._ctx = new import_context5.Context();
@@ -2034,12 +2055,12 @@ var NotarizationPlugin = class {
2034
2055
  /**
2035
2056
  * Request credentials to be notarized.
2036
2057
  */
2037
- async notarize(credentials) {
2058
+ async notarize({ ctx: opCtx, credentials, timeout = DEFAULT_NOTARIZE_TIMEOUT, retryTimeout = DEFAULT_RETRY_TIMEOUT, successDelay = DEFAULT_SUCCESS_DELAY }) {
2038
2059
  (0, import_log7.log)("notarize", {
2039
2060
  credentials
2040
2061
  }, {
2041
2062
  file: "notarization-plugin.ts",
2042
- line: 44,
2063
+ line: 85,
2043
2064
  scope: this,
2044
2065
  callSite: (f, a) => f(...a)
2045
2066
  });
@@ -2051,7 +2072,7 @@ var NotarizationPlugin = class {
2051
2072
  err
2052
2073
  }, {
2053
2074
  file: "notarization-plugin.ts",
2054
- line: 53,
2075
+ line: 94,
2055
2076
  scope: this,
2056
2077
  callSite: (f, a) => f(...a)
2057
2078
  });
@@ -2059,27 +2080,27 @@ var NotarizationPlugin = class {
2059
2080
  errors.throw(err);
2060
2081
  }
2061
2082
  });
2062
- (0, import_async9.scheduleTask)(ctx, () => {
2063
- import_log7.log.warn("Notarization timeout", {}, {
2064
- file: "notarization-plugin.ts",
2065
- line: 61,
2066
- scope: this,
2067
- callSite: (f, a) => f(...a)
2068
- });
2069
- void ctx.dispose();
2070
- errors.throw(new import_async9.TimeoutError(NOTARIZE_TIMEOUT, "Notarization timed out"));
2071
- }, NOTARIZE_TIMEOUT);
2083
+ opCtx == null ? void 0 : opCtx.onDispose(() => ctx.dispose());
2084
+ if (timeout !== 0) {
2085
+ (0, import_async9.scheduleTask)(ctx, () => {
2086
+ import_log7.log.warn("Notarization timeout", {
2087
+ timeout,
2088
+ peers: Array.from(this._extensions).map((extension) => extension.remotePeerId)
2089
+ }, {
2090
+ file: "notarization-plugin.ts",
2091
+ line: 106,
2092
+ scope: this,
2093
+ callSite: (f, a) => f(...a)
2094
+ });
2095
+ void ctx.dispose();
2096
+ errors.throw(new import_async9.TimeoutError(timeout, "Notarization timed out"));
2097
+ }, timeout);
2098
+ }
2072
2099
  const allNotarized = Promise.all(credentials.map((credential) => this._waitUntilProcessed(credential.id)));
2073
2100
  const peersTried = /* @__PURE__ */ new Set();
2074
2101
  const notarizeTask = new import_async9.DeferredTask(ctx, async () => {
2075
2102
  try {
2076
2103
  if (this._extensions.size === 0) {
2077
- import_log7.log.warn("No peers to notarize with", {}, {
2078
- file: "notarization-plugin.ts",
2079
- line: 76,
2080
- scope: this,
2081
- callSite: (f, a) => f(...a)
2082
- });
2083
2104
  return;
2084
2105
  }
2085
2106
  const peer = [
@@ -2087,15 +2108,15 @@ var NotarizationPlugin = class {
2087
2108
  ].find((peer2) => !peersTried.has(peer2));
2088
2109
  if (!peer) {
2089
2110
  import_log7.log.warn("Exhausted all peers to notarize with", {
2090
- retryIn: RETRY_TIMEOUT
2111
+ retryIn: retryTimeout
2091
2112
  }, {
2092
2113
  file: "notarization-plugin.ts",
2093
- line: 83,
2114
+ line: 131,
2094
2115
  scope: this,
2095
2116
  callSite: (f, a) => f(...a)
2096
2117
  });
2097
2118
  peersTried.clear();
2098
- (0, import_async9.scheduleTask)(ctx, () => notarizeTask.schedule(), RETRY_TIMEOUT);
2119
+ (0, import_async9.scheduleTask)(ctx, () => notarizeTask.schedule(), retryTimeout);
2099
2120
  return;
2100
2121
  }
2101
2122
  peersTried.add(peer);
@@ -2104,7 +2125,7 @@ var NotarizationPlugin = class {
2104
2125
  credentialId: credentials.map((credential) => credential.id)
2105
2126
  }, {
2106
2127
  file: "notarization-plugin.ts",
2107
- line: 90,
2128
+ line: 138,
2108
2129
  scope: this,
2109
2130
  callSite: (f, a) => f(...a)
2110
2131
  });
@@ -2113,14 +2134,15 @@ var NotarizationPlugin = class {
2113
2134
  });
2114
2135
  (0, import_log7.log)("success", {}, {
2115
2136
  file: "notarization-plugin.ts",
2116
- line: 94,
2137
+ line: 142,
2117
2138
  scope: this,
2118
2139
  callSite: (f, a) => f(...a)
2119
2140
  });
2141
+ await (0, import_async9.sleep)(successDelay);
2120
2142
  } catch (err) {
2121
2143
  import_log7.log.warn("error notarizing (recoverable)", err, {
2122
2144
  file: "notarization-plugin.ts",
2123
- line: 96,
2145
+ line: 145,
2124
2146
  scope: this,
2125
2147
  callSite: (f, a) => f(...a)
2126
2148
  });
@@ -2131,12 +2153,13 @@ var NotarizationPlugin = class {
2131
2153
  this._extensionOpened.on(ctx, () => notarizeTask.schedule());
2132
2154
  try {
2133
2155
  await Promise.race([
2156
+ (0, import_context5.rejectOnDispose)(ctx),
2134
2157
  allNotarized,
2135
2158
  errors.wait()
2136
2159
  ]);
2137
2160
  (0, import_log7.log)("done", {}, {
2138
2161
  file: "notarization-plugin.ts",
2139
- line: 107,
2162
+ line: 155,
2140
2163
  scope: this,
2141
2164
  callSite: (f, a) => f(...a)
2142
2165
  });
@@ -2189,7 +2212,7 @@ var NotarizationPlugin = class {
2189
2212
  peer: extension.localPeerId
2190
2213
  }, {
2191
2214
  file: "notarization-plugin.ts",
2192
- line: 156,
2215
+ line: 204,
2193
2216
  scope: this,
2194
2217
  callSite: (f, a) => f(...a)
2195
2218
  });
@@ -2201,7 +2224,7 @@ var NotarizationPlugin = class {
2201
2224
  peer: extension.localPeerId
2202
2225
  }, {
2203
2226
  file: "notarization-plugin.ts",
2204
- line: 161,
2227
+ line: 209,
2205
2228
  scope: this,
2206
2229
  callSite: (f, a) => f(...a)
2207
2230
  });
@@ -2255,17 +2278,22 @@ var __decorate = function(decorators, target, key, desc) {
2255
2278
  return c > 3 && r && Object.defineProperty(target, key, r), r;
2256
2279
  };
2257
2280
  var AUTH_TIMEOUT2 = 3e4;
2258
- var CONTROL_PIPELINE_READY_TIMEFRAME = 3e3;
2259
2281
  var DataSpace = class DataSpace2 {
2260
2282
  constructor(params) {
2261
2283
  this._ctx = new import_context6.Context();
2284
+ this._state = import_client3.SpaceState.CLOSED;
2285
+ this.stateUpdate = new import_async10.Event();
2286
+ var _a;
2262
2287
  this._inner = params.inner;
2288
+ this._inner.stateUpdate.on(this._ctx, () => this.stateUpdate.emit());
2289
+ this._gossip = params.gossip;
2263
2290
  this._presence = params.presence;
2264
2291
  this._keyring = params.keyring;
2265
2292
  this._feedStore = params.feedStore;
2266
2293
  this._metadataStore = params.metadataStore;
2267
2294
  this._signingContext = params.signingContext;
2268
- this._dataPipelineController = new import_echo_pipeline.DataPipelineControllerImpl({
2295
+ this._callbacks = (_a = params.callbacks) != null ? _a : {};
2296
+ this._dataPipeline = new import_echo_pipeline.DataPipeline({
2269
2297
  modelFactory: params.modelFactory,
2270
2298
  metadataStore: params.metadataStore,
2271
2299
  snapshotManager: params.snapshotManager,
@@ -2287,15 +2315,15 @@ var DataSpace = class DataSpace2 {
2287
2315
  get isOpen() {
2288
2316
  return this._inner.isOpen;
2289
2317
  }
2318
+ get state() {
2319
+ return this._state;
2320
+ }
2290
2321
  // TODO(burdon): Can we mark this for debugging only?
2291
2322
  get inner() {
2292
2323
  return this._inner;
2293
2324
  }
2294
- get dataPipelineController() {
2295
- return this._dataPipelineController;
2296
- }
2297
- get stateUpdate() {
2298
- return this._inner.stateUpdate;
2325
+ get dataPipeline() {
2326
+ return this._dataPipeline;
2299
2327
  }
2300
2328
  get presence() {
2301
2329
  return this._presence;
@@ -2307,26 +2335,102 @@ var DataSpace = class DataSpace2 {
2307
2335
  await this.notarizationPlugin.open();
2308
2336
  await this._notarizationPluginConsumer.open();
2309
2337
  await this._inner.open();
2338
+ this._state = import_client3.SpaceState.INACTIVE;
2310
2339
  }
2311
2340
  async close() {
2341
+ this._state = import_client3.SpaceState.CLOSED;
2312
2342
  await this._ctx.dispose();
2343
+ await this._dataPipeline.close();
2313
2344
  await this.authVerifier.close();
2314
2345
  await this._inner.close();
2315
2346
  await this._notarizationPluginConsumer.close();
2316
2347
  await this.notarizationPlugin.close();
2317
2348
  await this._presence.destroy();
2318
2349
  }
2350
+ async postMessage(channel, message) {
2351
+ return this._gossip.postMessage(channel, message);
2352
+ }
2353
+ listen(channel, callback) {
2354
+ return this._gossip.listen(channel, callback);
2355
+ }
2356
+ /**
2357
+ * Initialize the data pipeline in a separate task.
2358
+ */
2359
+ initializeDataPipelineAsync() {
2360
+ (0, import_async10.scheduleTask)(this._ctx, async () => {
2361
+ try {
2362
+ await this.initializeDataPipeline();
2363
+ } catch (err) {
2364
+ if (err instanceof import_errors.CancelledError) {
2365
+ (0, import_log8.log)("Data pipeline initialization cancelled", err, {
2366
+ file: "data-space.ts",
2367
+ line: 178,
2368
+ scope: this,
2369
+ callSite: (f, a) => f(...a)
2370
+ });
2371
+ return;
2372
+ }
2373
+ import_log8.log.error("Error initializing data pipeline", err, {
2374
+ file: "data-space.ts",
2375
+ line: 182,
2376
+ scope: this,
2377
+ callSite: (f, a) => f(...a)
2378
+ });
2379
+ }
2380
+ });
2381
+ }
2319
2382
  async initializeDataPipeline() {
2383
+ var _a, _b, _c, _d;
2384
+ if (this._state !== import_client3.SpaceState.INACTIVE) {
2385
+ throw new import_errors.SystemError("Invalid operation");
2386
+ }
2387
+ this._state = import_client3.SpaceState.INITIALIZING;
2320
2388
  await this._inner.controlPipeline.state.waitUntilReachedTargetTimeframe({
2321
- timeout: CONTROL_PIPELINE_READY_TIMEFRAME
2389
+ ctx: this._ctx,
2390
+ breakOnStall: false
2322
2391
  });
2323
2392
  await this._createWritableFeeds();
2393
+ (0, import_log8.log)("Writable feeds created", {}, {
2394
+ file: "data-space.ts",
2395
+ line: 200,
2396
+ scope: this,
2397
+ callSite: (f, a) => f(...a)
2398
+ });
2399
+ this.stateUpdate.emit();
2324
2400
  this.notarizationPlugin.setWriter((0, import_echo_pipeline.createMappedFeedWriter)((credential) => ({
2325
2401
  credential: {
2326
2402
  credential
2327
2403
  }
2328
2404
  }), this._inner.controlPipeline.writer));
2329
- await this._inner.initDataPipeline(this._dataPipelineController);
2405
+ await this._dataPipeline.open({
2406
+ openPipeline: async (start) => {
2407
+ const pipeline = await this._inner.createDataPipeline({
2408
+ start
2409
+ });
2410
+ await pipeline.start();
2411
+ return pipeline;
2412
+ }
2413
+ });
2414
+ (0, import_log8.log)("waiting for data pipeline to reach target timeframe", {}, {
2415
+ file: "data-space.ts",
2416
+ line: 220,
2417
+ scope: this,
2418
+ callSite: (f, a) => f(...a)
2419
+ });
2420
+ await this._dataPipeline.pipelineState.waitUntilReachedTargetTimeframe({
2421
+ ctx: this._ctx,
2422
+ breakOnStall: false
2423
+ });
2424
+ (0, import_log8.log)("data pipeline ready", {}, {
2425
+ file: "data-space.ts",
2426
+ line: 227,
2427
+ scope: this,
2428
+ callSite: (f, a) => f(...a)
2429
+ });
2430
+ await ((_b = (_a = this._callbacks).beforeReady) == null ? void 0 : _b.call(_a));
2431
+ this._state = import_client3.SpaceState.READY;
2432
+ this.stateUpdate.emit();
2433
+ await ((_d = (_c = this._callbacks).afterReady) == null ? void 0 : _d.call(_c));
2330
2434
  }
2331
2435
  async _createWritableFeeds() {
2332
2436
  const credentials = [];
@@ -2363,7 +2467,11 @@ var DataSpace = class DataSpace2 {
2363
2467
  }));
2364
2468
  }
2365
2469
  if (credentials.length > 0) {
2366
- await this.notarizationPlugin.notarize(credentials);
2470
+ await this.notarizationPlugin.notarize({
2471
+ ctx: this._ctx,
2472
+ credentials,
2473
+ timeout: 0
2474
+ });
2367
2475
  }
2368
2476
  await this._metadataStore.setWritableFeedKeys(this.key, this.inner.controlFeedKey, this.inner.dataFeedKey);
2369
2477
  }
@@ -2386,7 +2494,6 @@ var __decorate2 = function(decorators, target, key, desc) {
2386
2494
  r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
2387
2495
  return c > 3 && r && Object.defineProperty(target, key, r), r;
2388
2496
  };
2389
- var DATA_PIPELINE_READY_TIMEOUT = 3e3;
2390
2497
  var DataSpaceManager = class DataSpaceManager2 {
2391
2498
  constructor(_spaceManager, _metadataStore, _dataServiceSubscriptions, _keyring, _signingContext, _modelFactory, _feedStore, _snapshotStore) {
2392
2499
  this._spaceManager = _spaceManager;
@@ -2400,50 +2507,51 @@ var DataSpaceManager = class DataSpaceManager2 {
2400
2507
  this._ctx = new import_context7.Context();
2401
2508
  this.updated = new import_async11.Event();
2402
2509
  this._spaces = new import_util5.ComplexMap(import_keys9.PublicKey.hash);
2510
+ this._isOpen = false;
2403
2511
  }
2404
2512
  // TODO(burdon): Remove.
2405
2513
  get spaces() {
2406
2514
  return this._spaces;
2407
2515
  }
2408
2516
  async open() {
2517
+ (0, import_log9.log)("open", {}, {
2518
+ file: "data-space-manager.ts",
2519
+ line: 80,
2520
+ scope: this,
2521
+ callSite: (f, a) => f(...a)
2522
+ });
2409
2523
  await this._metadataStore.load();
2410
- (0, import_log8.log)("metadata loaded", {
2524
+ (0, import_log9.log)("metadata loaded", {
2411
2525
  spaces: this._metadataStore.spaces.length
2412
2526
  }, {
2413
2527
  file: "data-space-manager.ts",
2414
- line: 67,
2528
+ line: 82,
2415
2529
  scope: this,
2416
2530
  callSite: (f, a) => f(...a)
2417
2531
  });
2418
2532
  for (const spaceMetadata of this._metadataStore.spaces) {
2419
- (0, import_log8.log)("load space", {
2533
+ (0, import_log9.log)("load space", {
2420
2534
  spaceMetadata
2421
2535
  }, {
2422
2536
  file: "data-space-manager.ts",
2423
- line: 70,
2537
+ line: 85,
2424
2538
  scope: this,
2425
2539
  callSite: (f, a) => f(...a)
2426
2540
  });
2427
2541
  const space = await this._constructSpace(spaceMetadata);
2428
- await space.initializeDataPipeline();
2429
- if (spaceMetadata.dataTimeframe) {
2430
- (0, import_log8.log)("waiting for latest timeframe", {
2431
- spaceMetadata
2432
- }, {
2433
- file: "data-space-manager.ts",
2434
- line: 74,
2435
- scope: this,
2436
- callSite: (f, a) => f(...a)
2437
- });
2438
- await space.dataPipelineController.pipelineState.setTargetTimeframe(spaceMetadata.dataTimeframe);
2439
- }
2440
- await space.dataPipelineController.pipelineState.waitUntilReachedTargetTimeframe({
2441
- timeout: DATA_PIPELINE_READY_TIMEOUT
2442
- });
2443
- this._dataServiceSubscriptions.registerSpace(space.key, space.dataPipelineController.databaseBackend.createDataServiceHost());
2542
+ space.initializeDataPipelineAsync();
2444
2543
  }
2544
+ this._isOpen = true;
2545
+ this.updated.emit();
2445
2546
  }
2446
2547
  async close() {
2548
+ (0, import_log9.log)("close", {}, {
2549
+ file: "data-space-manager.ts",
2550
+ line: 96,
2551
+ scope: this,
2552
+ callSite: (f, a) => f(...a)
2553
+ });
2554
+ this._isOpen = false;
2447
2555
  await this._ctx.dispose();
2448
2556
  for (const space of this._spaces.values()) {
2449
2557
  await space.close();
@@ -2453,6 +2561,7 @@ var DataSpaceManager = class DataSpaceManager2 {
2453
2561
  * Creates a new space writing the genesis credentials to the control feed.
2454
2562
  */
2455
2563
  async createSpace() {
2564
+ (0, import_node_assert9.default)(this._isOpen, "Not open.");
2456
2565
  const spaceKey = await this._keyring.createKey();
2457
2566
  const controlFeedKey = await this._keyring.createKey();
2458
2567
  const dataFeedKey = await this._keyring.createKey();
@@ -2462,11 +2571,11 @@ var DataSpaceManager = class DataSpaceManager2 {
2462
2571
  controlFeedKey,
2463
2572
  dataFeedKey
2464
2573
  };
2465
- (0, import_log8.log)("creating space...", {
2574
+ (0, import_log9.log)("creating space...", {
2466
2575
  spaceKey
2467
2576
  }, {
2468
2577
  file: "data-space-manager.ts",
2469
- line: 110,
2578
+ line: 120,
2470
2579
  scope: this,
2471
2580
  callSite: (f, a) => f(...a)
2472
2581
  });
@@ -2477,30 +2586,61 @@ var DataSpaceManager = class DataSpaceManager2 {
2477
2586
  (0, import_node_assert9.default)((0, import_credentials11.getCredentialAssertion)(memberCredential)["@type"] === "dxos.halo.credentials.SpaceMember");
2478
2587
  await this._signingContext.recordCredential(memberCredential);
2479
2588
  await space.initializeDataPipeline();
2480
- this._dataServiceSubscriptions.registerSpace(space.key, space.dataPipelineController.databaseBackend.createDataServiceHost());
2481
2589
  this.updated.emit();
2482
2590
  return space;
2483
2591
  }
2484
2592
  // TODO(burdon): Rename join space.
2485
2593
  async acceptSpace(opts) {
2594
+ (0, import_log9.log)("accept space", {
2595
+ opts
2596
+ }, {
2597
+ file: "data-space-manager.ts",
2598
+ line: 139,
2599
+ scope: this,
2600
+ callSite: (f, a) => f(...a)
2601
+ });
2602
+ (0, import_node_assert9.default)(this._isOpen, "Not open.");
2486
2603
  (0, import_node_assert9.default)(!this._spaces.has(opts.spaceKey), "Space already exists.");
2487
2604
  const metadata = {
2488
2605
  key: opts.spaceKey,
2489
- genesisFeedKey: opts.genesisFeedKey
2606
+ genesisFeedKey: opts.genesisFeedKey,
2607
+ controlTimeframe: opts.controlTimeframe,
2608
+ dataTimeframe: opts.dataTimeframe
2490
2609
  };
2491
2610
  const space = await this._constructSpace(metadata);
2492
2611
  await this._metadataStore.addSpace(metadata);
2493
- await space.initializeDataPipeline();
2494
- this._dataServiceSubscriptions.registerSpace(space.key, space.dataPipelineController.databaseBackend.createDataServiceHost());
2612
+ space.initializeDataPipelineAsync();
2495
2613
  this.updated.emit();
2496
2614
  return space;
2497
2615
  }
2616
+ /**
2617
+ * Wait until the space data pipeline is fully initialized.
2618
+ * Used by invitation handler.
2619
+ * TODO(dmaretskyi): Consider removing.
2620
+ */
2621
+ async waitUntilSpaceReady(spaceKey) {
2622
+ await (0, import_context7.cancelWithContext)(this._ctx, this.updated.waitForCondition(() => {
2623
+ const space = this._spaces.get(spaceKey);
2624
+ return !!space && space.state === import_client4.SpaceState.READY;
2625
+ }));
2626
+ }
2498
2627
  async _constructSpace(metadata) {
2499
- const presence = new import_teleport_extension_presence.Presence({
2500
- localPeerId: this._signingContext.deviceKey,
2501
- announceInterval: 1e3,
2502
- offlineTimeout: 1e4,
2503
- identityKey: this._signingContext.identityKey
2628
+ (0, import_log9.log)("construct space", {
2629
+ metadata
2630
+ }, {
2631
+ file: "data-space-manager.ts",
2632
+ line: 175,
2633
+ scope: this,
2634
+ callSite: (f, a) => f(...a)
2635
+ });
2636
+ const gossip = new import_teleport_extension_gossip.Gossip({
2637
+ localPeerId: this._signingContext.deviceKey
2638
+ });
2639
+ const presence = new import_teleport_extension_gossip.Presence({
2640
+ announceInterval: 500,
2641
+ offlineTimeout: 5e3,
2642
+ identityKey: this._signingContext.identityKey,
2643
+ gossip
2504
2644
  });
2505
2645
  const snapshotManager = new import_echo_pipeline2.SnapshotManager(this._snapshotStore);
2506
2646
  const controlFeed = metadata.controlFeedKey && await this._feedStore.openFeed(metadata.controlFeedKey, {
@@ -2517,7 +2657,7 @@ var DataSpaceManager = class DataSpaceManager2 {
2517
2657
  credentialAuthenticator: (0, import_util5.deferFunction)(() => dataSpace.authVerifier.verifier)
2518
2658
  },
2519
2659
  onNetworkConnection: (session) => {
2520
- session.addExtension("dxos.mesh.teleport.presence", presence.createExtension({
2660
+ session.addExtension("dxos.mesh.teleport.gossip", gossip.createExtension({
2521
2661
  remotePeerId: session.remotePeerId
2522
2662
  }));
2523
2663
  session.addExtension("dxos.mesh.teleport.objectsync", snapshotManager.objectSync.createExtension());
@@ -2531,14 +2671,48 @@ var DataSpaceManager = class DataSpaceManager2 {
2531
2671
  modelFactory: this._modelFactory,
2532
2672
  metadataStore: this._metadataStore,
2533
2673
  snapshotManager,
2674
+ gossip,
2534
2675
  presence,
2535
2676
  memberKey: this._signingContext.identityKey,
2536
2677
  keyring: this._keyring,
2537
2678
  feedStore: this._feedStore,
2538
2679
  signingContext: this._signingContext,
2539
- snapshotId: metadata.snapshot
2680
+ snapshotId: metadata.snapshot,
2681
+ callbacks: {
2682
+ beforeReady: async () => {
2683
+ (0, import_log9.log)("before space ready", {
2684
+ space: space.key
2685
+ }, {
2686
+ file: "data-space-manager.ts",
2687
+ line: 224,
2688
+ scope: this,
2689
+ callSite: (f, a) => f(...a)
2690
+ });
2691
+ this._dataServiceSubscriptions.registerSpace(space.key, dataSpace.dataPipeline.databaseBackend.createDataServiceHost());
2692
+ },
2693
+ afterReady: async () => {
2694
+ (0, import_log9.log)("after space ready", {
2695
+ space: space.key,
2696
+ open: this._isOpen
2697
+ }, {
2698
+ file: "data-space-manager.ts",
2699
+ line: 231,
2700
+ scope: this,
2701
+ callSite: (f, a) => f(...a)
2702
+ });
2703
+ if (this._isOpen) {
2704
+ this.updated.emit();
2705
+ }
2706
+ }
2707
+ }
2540
2708
  });
2541
2709
  await dataSpace.open();
2710
+ if (metadata.controlTimeframe) {
2711
+ dataSpace.inner.controlPipeline.state.setTargetTimeframe(metadata.controlTimeframe);
2712
+ }
2713
+ if (metadata.dataTimeframe) {
2714
+ dataSpace.dataPipeline.setTargetTimeframe(metadata.dataTimeframe);
2715
+ }
2542
2716
  this._spaces.set(metadata.key, dataSpace);
2543
2717
  return dataSpace;
2544
2718
  }
@@ -2564,9 +2738,10 @@ var import_async12 = require("@dxos/async");
2564
2738
  var import_codec_protobuf10 = require("@dxos/codec-protobuf");
2565
2739
  var import_debug4 = require("@dxos/debug");
2566
2740
  var import_echo_pipeline3 = require("@dxos/echo-pipeline");
2567
- var import_log9 = require("@dxos/log");
2741
+ var import_log10 = require("@dxos/log");
2568
2742
  var import_services5 = require("@dxos/protocols/proto/dxos/client/services");
2569
2743
  var import_util6 = require("@dxos/util");
2744
+ var TIMEFRAME_UPDATE_DEBOUNCE_TIME = 500;
2570
2745
  var SpacesServiceImpl = class {
2571
2746
  constructor(_identityManager, _spaceManager, _dataServiceSubscriptions, _getDataSpaceManager) {
2572
2747
  this._identityManager = _identityManager;
@@ -2589,12 +2764,12 @@ var SpacesServiceImpl = class {
2589
2764
  return new import_codec_protobuf10.Stream(({ next, ctx }) => {
2590
2765
  const onUpdate = async () => {
2591
2766
  const dataSpaceManager = await this._getDataSpaceManager();
2592
- const spaces = Array.from(dataSpaceManager.spaces.values()).filter((space) => this._dataServiceSubscriptions.getDataService(space.key)).map((space) => this._transformSpace(space));
2593
- (0, import_log9.log)("update", {
2767
+ const spaces = Array.from(dataSpaceManager.spaces.values()).map((space) => this._transformSpace(space));
2768
+ (0, import_log10.log)("update", {
2594
2769
  spaces
2595
2770
  }, {
2596
2771
  file: "spaces-service.ts",
2597
- line: 59,
2772
+ line: 60,
2598
2773
  scope: this,
2599
2774
  callSite: (f, a) => f(...a)
2600
2775
  });
@@ -2602,28 +2777,27 @@ var SpacesServiceImpl = class {
2602
2777
  spaces
2603
2778
  });
2604
2779
  };
2605
- setTimeout(async () => {
2780
+ (0, import_async12.scheduleTask)(ctx, async () => {
2606
2781
  const dataSpaceManager = await this._getDataSpaceManager();
2607
2782
  const subscriptions = new import_async12.EventSubscriptions();
2783
+ ctx.onDispose(() => subscriptions.clear());
2608
2784
  const subscribeSpaces = () => {
2609
2785
  subscriptions.clear();
2610
2786
  for (const space of dataSpaceManager.spaces.values()) {
2611
- if (!this._dataServiceSubscriptions.getDataService(space.key)) {
2612
- continue;
2613
- }
2614
2787
  subscriptions.add(space.stateUpdate.on(ctx, onUpdate));
2615
2788
  subscriptions.add(space.presence.updated.on(ctx, onUpdate));
2789
+ space.inner.controlPipeline.state.timeframeUpdate.debounce(TIMEFRAME_UPDATE_DEBOUNCE_TIME).on(ctx, onUpdate);
2790
+ if (space.dataPipeline.pipelineState) {
2791
+ subscriptions.add(space.dataPipeline.pipelineState.timeframeUpdate.debounce(TIMEFRAME_UPDATE_DEBOUNCE_TIME).on(ctx, onUpdate));
2792
+ }
2616
2793
  }
2617
2794
  };
2618
2795
  dataSpaceManager.updated.on(ctx, () => {
2619
2796
  subscribeSpaces();
2620
2797
  void onUpdate();
2621
2798
  });
2622
- ctx.onDispose(() => subscriptions.clear());
2623
- (0, import_async12.scheduleTask)(ctx, () => {
2624
- subscribeSpaces();
2625
- void onUpdate();
2626
- });
2799
+ subscribeSpaces();
2800
+ void onUpdate();
2627
2801
  });
2628
2802
  if (!this._identityManager.identity) {
2629
2803
  next({
@@ -2632,6 +2806,25 @@ var SpacesServiceImpl = class {
2632
2806
  }
2633
2807
  });
2634
2808
  }
2809
+ async postMessage({ spaceKey, channel, message }) {
2810
+ var _a;
2811
+ const dataSpaceManager = await this._getDataSpaceManager();
2812
+ const space = (_a = dataSpaceManager.spaces.get(spaceKey)) != null ? _a : (0, import_debug4.raise)(new import_echo_pipeline3.SpaceNotFoundError(spaceKey));
2813
+ await space.postMessage(getChannelId(channel), message);
2814
+ }
2815
+ subscribeMessages({ spaceKey, channel }) {
2816
+ return new import_codec_protobuf10.Stream(({ ctx, next }) => {
2817
+ (0, import_async12.scheduleTask)(ctx, async () => {
2818
+ var _a;
2819
+ const dataSpaceManager = await this._getDataSpaceManager();
2820
+ const space = (_a = dataSpaceManager.spaces.get(spaceKey)) != null ? _a : (0, import_debug4.raise)(new import_echo_pipeline3.SpaceNotFoundError(spaceKey));
2821
+ const handle = space.listen(getChannelId(channel), (message) => {
2822
+ next(message);
2823
+ });
2824
+ ctx.onDispose(() => handle.unsubscribe());
2825
+ });
2826
+ });
2827
+ }
2635
2828
  queryCredentials({ spaceKey }) {
2636
2829
  return new import_codec_protobuf10.Stream(({ ctx, next }) => {
2637
2830
  var _a;
@@ -2657,16 +2850,23 @@ var SpacesServiceImpl = class {
2657
2850
  }
2658
2851
  }
2659
2852
  _transformSpace(space) {
2853
+ var _a, _b;
2660
2854
  return {
2661
2855
  spaceKey: space.key,
2662
- status: space.isOpen ? import_services5.SpaceStatus.ACTIVE : import_services5.SpaceStatus.INACTIVE,
2856
+ state: space.state,
2857
+ pipeline: {
2858
+ targetControlTimeframe: space.inner.controlPipeline.state.targetTimeframe,
2859
+ currentControlTimeframe: space.inner.controlPipeline.state.timeframe,
2860
+ currentDataTimeframe: (_a = space.dataPipeline.pipelineState) == null ? void 0 : _a.timeframe,
2861
+ targetDataTimeframe: (_b = space.dataPipeline.pipelineState) == null ? void 0 : _b.targetTimeframe
2862
+ },
2663
2863
  members: Array.from(space.inner.spaceState.members.values()).map((member) => {
2664
- var _a, _b, _c;
2864
+ var _a2, _b2, _c;
2665
2865
  return {
2666
2866
  identity: {
2667
2867
  identityKey: member.key,
2668
2868
  profile: {
2669
- displayName: (_b = (_a = member.assertion.profile) == null ? void 0 : _a.displayName) != null ? _b : (0, import_util6.humanize)(member.key)
2869
+ displayName: (_b2 = (_a2 = member.assertion.profile) == null ? void 0 : _a2.displayName) != null ? _b2 : (0, import_util6.humanize)(member.key)
2670
2870
  }
2671
2871
  },
2672
2872
  presence: ((_c = this._identityManager.identity) == null ? void 0 : _c.identityKey.equals(member.key)) || space.presence.getPeersOnline().filter(({ identityKey }) => identityKey.equals(member.key)).length > 0 ? import_services5.SpaceMember.PresenceState.ONLINE : import_services5.SpaceMember.PresenceState.OFFLINE
@@ -2675,25 +2875,26 @@ var SpacesServiceImpl = class {
2675
2875
  };
2676
2876
  }
2677
2877
  };
2878
+ var getChannelId = (channel) => `user-channel/${channel}`;
2678
2879
 
2679
2880
  // packages/sdk/client-services/src/packlets/storage/storage.ts
2680
- var import_errors = require("@dxos/errors");
2881
+ var import_errors2 = require("@dxos/errors");
2681
2882
  var import_config = require("@dxos/protocols/proto/dxos/config");
2682
2883
  var import_random_access_storage = require("@dxos/random-access-storage");
2683
2884
  var StorageDriver = import_config.Runtime.Client.Storage.StorageDriver;
2684
2885
  var createStorageObjects = (config) => {
2685
2886
  const { path = "dxos/storage", storageType, keyStorage, persistent = false } = config != null ? config : {};
2686
2887
  if (persistent && storageType === StorageDriver.RAM) {
2687
- throw new import_errors.InvalidConfigError("RAM storage cannot be used in persistent mode.");
2888
+ throw new import_errors2.InvalidConfigError("RAM storage cannot be used in persistent mode.");
2688
2889
  }
2689
2890
  if (!persistent && storageType !== void 0 && storageType !== StorageDriver.RAM) {
2690
- throw new import_errors.InvalidConfigError("Cannot use a persistent storage in not persistent mode.");
2891
+ throw new import_errors2.InvalidConfigError("Cannot use a persistent storage in not persistent mode.");
2691
2892
  }
2692
2893
  if (persistent && keyStorage === StorageDriver.RAM) {
2693
- throw new import_errors.InvalidConfigError("RAM key storage cannot be used in persistent mode.");
2894
+ throw new import_errors2.InvalidConfigError("RAM key storage cannot be used in persistent mode.");
2694
2895
  }
2695
2896
  if (!persistent && keyStorage !== StorageDriver.RAM && keyStorage !== void 0) {
2696
- throw new import_errors.InvalidConfigError("Cannot use a persistent key storage in not persistent mode.");
2897
+ throw new import_errors2.InvalidConfigError("Cannot use a persistent key storage in not persistent mode.");
2697
2898
  }
2698
2899
  return {
2699
2900
  storage: (0, import_random_access_storage.createStorage)({
@@ -2761,7 +2962,7 @@ var SystemServiceImpl = class {
2761
2962
 
2762
2963
  // packages/sdk/client-services/src/packlets/vault/iframe-host-runtime.ts
2763
2964
  var import_async14 = require("@dxos/async");
2764
- var import_log10 = require("@dxos/log");
2965
+ var import_log11 = require("@dxos/log");
2765
2966
  var import_messaging = require("@dxos/messaging");
2766
2967
  var import_network_manager3 = require("@dxos/network-manager");
2767
2968
  var import_util7 = require("@dxos/util");
@@ -2822,7 +3023,7 @@ var ClientRpcServer = class {
2822
3023
  // packages/sdk/client-services/src/packlets/vault/shell-runtime.ts
2823
3024
  var import_node_assert10 = __toESM(require("node:assert"));
2824
3025
  var import_async13 = require("@dxos/async");
2825
- var import_client3 = require("@dxos/client");
3026
+ var import_client5 = require("@dxos/client");
2826
3027
  var import_iframe = require("@dxos/protocols/proto/dxos/iframe");
2827
3028
  var import_rpc2 = require("@dxos/rpc");
2828
3029
  var ShellRuntimeImpl = class {
@@ -2855,8 +3056,8 @@ var ShellRuntimeImpl = class {
2855
3056
  }
2856
3057
  async open() {
2857
3058
  this._appRpc = (0, import_rpc2.createProtoRpcPeer)({
2858
- requested: import_client3.appServiceBundle,
2859
- exposed: import_client3.shellServiceBundle,
3059
+ requested: import_client5.appServiceBundle,
3060
+ exposed: import_client5.shellServiceBundle,
2860
3061
  handlers: {
2861
3062
  ShellService: {
2862
3063
  setLayout: async (request) => {
@@ -2909,7 +3110,7 @@ var IFrameHostRuntime = class {
2909
3110
  }
2910
3111
  async start() {
2911
3112
  var _a;
2912
- (0, import_log10.log)("starting...", {}, {
3113
+ (0, import_log11.log)("starting...", {}, {
2913
3114
  file: "iframe-host-runtime.ts",
2914
3115
  line: 67,
2915
3116
  scope: this,
@@ -2960,7 +3161,7 @@ var IFrameHostRuntime = class {
2960
3161
  (_a = this._shellRuntime) == null ? void 0 : _a.open()
2961
3162
  ]);
2962
3163
  this._ready.wake(void 0);
2963
- (0, import_log10.log)("started", {}, {
3164
+ (0, import_log11.log)("started", {}, {
2964
3165
  file: "iframe-host-runtime.ts",
2965
3166
  line: 110,
2966
3167
  scope: this,
@@ -2968,7 +3169,7 @@ var IFrameHostRuntime = class {
2968
3169
  });
2969
3170
  } catch (err) {
2970
3171
  this._ready.wake(err);
2971
- import_log10.log.catch(err, {}, {
3172
+ import_log11.log.catch(err, {}, {
2972
3173
  file: "iframe-host-runtime.ts",
2973
3174
  line: 113,
2974
3175
  scope: this,
@@ -2978,7 +3179,7 @@ var IFrameHostRuntime = class {
2978
3179
  }
2979
3180
  async stop() {
2980
3181
  var _a;
2981
- (0, import_log10.log)("stopping...", {}, {
3182
+ (0, import_log11.log)("stopping...", {}, {
2982
3183
  file: "iframe-host-runtime.ts",
2983
3184
  line: 118,
2984
3185
  scope: this,
@@ -2987,7 +3188,7 @@ var IFrameHostRuntime = class {
2987
3188
  await this._clientRpc.close();
2988
3189
  await this._clientServices.close();
2989
3190
  await ((_a = this._shellRuntime) == null ? void 0 : _a.close());
2990
- (0, import_log10.log)("stopped", {}, {
3191
+ (0, import_log11.log)("stopped", {}, {
2991
3192
  file: "iframe-host-runtime.ts",
2992
3193
  line: 122,
2993
3194
  scope: this,
@@ -2996,17 +3197,27 @@ var IFrameHostRuntime = class {
2996
3197
  }
2997
3198
  };
2998
3199
  __decorate3([
2999
- import_log10.logInfo
3200
+ import_log11.logInfo
3000
3201
  ], IFrameHostRuntime.prototype, "origin", void 0);
3001
3202
 
3002
3203
  // packages/sdk/client-services/src/packlets/vault/iframe-proxy-runtime.ts
3003
- var import_client4 = require("@dxos/client");
3204
+ var import_client6 = require("@dxos/client");
3004
3205
  var import_network_manager4 = require("@dxos/network-manager");
3005
3206
  var import_rpc3 = require("@dxos/rpc");
3006
3207
 
3007
3208
  // packages/sdk/client-services/src/packlets/vault/vault-resource-lock.ts
3008
3209
  var import_async15 = require("@dxos/async");
3009
- var import_log11 = require("@dxos/log");
3210
+ var import_log12 = require("@dxos/log");
3211
+ var __decorate4 = function(decorators, target, key, desc) {
3212
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3213
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
3214
+ r = Reflect.decorate(decorators, target, key, desc);
3215
+ else
3216
+ for (var i = decorators.length - 1; i >= 0; i--)
3217
+ if (d = decorators[i])
3218
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
3219
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
3220
+ };
3010
3221
  var Message;
3011
3222
  (function(Message2) {
3012
3223
  Message2["ACQUIRING"] = "acquiring";
@@ -3020,14 +3231,41 @@ var VaultResourceLock = class {
3020
3231
  this._onRelease = onRelease;
3021
3232
  this._broadcastChannel.onmessage = this._onMessage.bind(this);
3022
3233
  }
3234
+ get lockKey() {
3235
+ return this._lockKey;
3236
+ }
3023
3237
  async acquire() {
3024
3238
  this._broadcastChannel.postMessage({
3025
3239
  message: Message.ACQUIRING
3026
3240
  });
3027
3241
  try {
3242
+ (0, import_log12.log)("aquiring lock...", {}, {
3243
+ file: "vault-resource-lock.ts",
3244
+ line: 44,
3245
+ scope: this,
3246
+ callSite: (f, a) => f(...a)
3247
+ });
3028
3248
  await (0, import_async15.asyncTimeout)(this._requestLock(), 3e3);
3249
+ (0, import_log12.log)("acquired lock", {}, {
3250
+ file: "vault-resource-lock.ts",
3251
+ line: 46,
3252
+ scope: this,
3253
+ callSite: (f, a) => f(...a)
3254
+ });
3029
3255
  } catch (e) {
3256
+ (0, import_log12.log)("stealing lock...", {}, {
3257
+ file: "vault-resource-lock.ts",
3258
+ line: 48,
3259
+ scope: this,
3260
+ callSite: (f, a) => f(...a)
3261
+ });
3030
3262
  await this._requestLock(true);
3263
+ (0, import_log12.log)("stolen lock", {}, {
3264
+ file: "vault-resource-lock.ts",
3265
+ line: 50,
3266
+ scope: this,
3267
+ callSite: (f, a) => f(...a)
3268
+ });
3031
3269
  }
3032
3270
  }
3033
3271
  async release() {
@@ -3039,11 +3277,11 @@ var VaultResourceLock = class {
3039
3277
  }
3040
3278
  }
3041
3279
  async _requestLock(steal = false) {
3042
- (0, import_log11.log)("requesting lock...", {
3280
+ (0, import_log12.log)("requesting lock...", {
3043
3281
  steal
3044
3282
  }, {
3045
3283
  file: "vault-resource-lock.ts",
3046
- line: 56,
3284
+ line: 65,
3047
3285
  scope: this,
3048
3286
  callSite: (f, a) => f(...a)
3049
3287
  });
@@ -3056,16 +3294,16 @@ var VaultResourceLock = class {
3056
3294
  acquired.wake();
3057
3295
  this._releaseTrigger = new import_async15.Trigger();
3058
3296
  await this._releaseTrigger.wait();
3059
- (0, import_log11.log)("releasing lock...", {}, {
3297
+ (0, import_log12.log)("releasing lock...", {}, {
3060
3298
  file: "vault-resource-lock.ts",
3061
- line: 65,
3299
+ line: 74,
3062
3300
  scope: this,
3063
3301
  callSite: (f, a) => f(...a)
3064
3302
  });
3065
3303
  await ((_b = this._onRelease) == null ? void 0 : _b.call(this));
3066
- (0, import_log11.log)("released lock", {}, {
3304
+ (0, import_log12.log)("released lock", {}, {
3067
3305
  file: "vault-resource-lock.ts",
3068
- line: 67,
3306
+ line: 76,
3069
3307
  scope: this,
3070
3308
  callSite: (f, a) => f(...a)
3071
3309
  });
@@ -3074,31 +3312,34 @@ var VaultResourceLock = class {
3074
3312
  await ((_a = this._onRelease) == null ? void 0 : _a.call(this));
3075
3313
  });
3076
3314
  await acquired.wait();
3077
- (0, import_log11.log)("recieved lock", {
3315
+ (0, import_log12.log)("recieved lock", {
3078
3316
  steal
3079
3317
  }, {
3080
3318
  file: "vault-resource-lock.ts",
3081
- line: 74,
3319
+ line: 83,
3082
3320
  scope: this,
3083
3321
  callSite: (f, a) => f(...a)
3084
3322
  });
3085
3323
  }
3086
3324
  };
3325
+ __decorate4([
3326
+ import_log12.logInfo
3327
+ ], VaultResourceLock.prototype, "lockKey", null);
3087
3328
 
3088
3329
  // packages/sdk/client-services/src/packlets/vault/worker-runtime.ts
3089
3330
  var import_async17 = require("@dxos/async");
3090
- var import_log13 = require("@dxos/log");
3331
+ var import_log14 = require("@dxos/log");
3091
3332
  var import_messaging2 = require("@dxos/messaging");
3092
3333
  var import_network_manager5 = require("@dxos/network-manager");
3093
3334
 
3094
3335
  // packages/sdk/client-services/src/packlets/vault/worker-session.ts
3095
3336
  var import_node_assert11 = __toESM(require("node:assert"));
3096
3337
  var import_async16 = require("@dxos/async");
3097
- var import_client5 = require("@dxos/client");
3098
- var import_log12 = require("@dxos/log");
3338
+ var import_client7 = require("@dxos/client");
3339
+ var import_log13 = require("@dxos/log");
3099
3340
  var import_rpc4 = require("@dxos/rpc");
3100
3341
  var import_util8 = require("@dxos/util");
3101
- var __decorate4 = function(decorators, target, key, desc) {
3342
+ var __decorate5 = function(decorators, target, key, desc) {
3102
3343
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3103
3344
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
3104
3345
  r = Reflect.decorate(decorators, target, key, desc);
@@ -3149,8 +3390,8 @@ var WorkerSession = class {
3149
3390
  ...middleware
3150
3391
  });
3151
3392
  this._iframeRpc = (0, import_rpc4.createProtoRpcPeer)({
3152
- requested: import_client5.iframeServiceBundle,
3153
- exposed: import_client5.workerServiceBundle,
3393
+ requested: import_client7.iframeServiceBundle,
3394
+ exposed: import_client7.workerServiceBundle,
3154
3395
  handlers: {
3155
3396
  WorkerService: {
3156
3397
  start: async (request) => {
@@ -3162,7 +3403,7 @@ var WorkerSession = class {
3162
3403
  try {
3163
3404
  await this.close();
3164
3405
  } catch (err) {
3165
- import_log12.log.catch(err, {}, {
3406
+ import_log13.log.catch(err, {}, {
3166
3407
  file: "worker-session.ts",
3167
3408
  line: 107,
3168
3409
  scope: this,
@@ -3180,7 +3421,7 @@ var WorkerSession = class {
3180
3421
  this.bridgeService = this._iframeRpc.rpc.BridgeService;
3181
3422
  }
3182
3423
  async open() {
3183
- import_log12.log.info("opening..", {}, {
3424
+ import_log13.log.info("opening..", {}, {
3184
3425
  file: "worker-session.ts",
3185
3426
  line: 121,
3186
3427
  scope: this,
@@ -3198,7 +3439,7 @@ var WorkerSession = class {
3198
3439
  try {
3199
3440
  await this._iframeRpc.rpc.IframeService.heartbeat();
3200
3441
  } catch (err1) {
3201
- import_log12.log.warn("Heartbeat failed", {
3442
+ import_log13.log.warn("Heartbeat failed", {
3202
3443
  err: err1
3203
3444
  }, {
3204
3445
  file: "worker-session.ts",
@@ -3209,7 +3450,7 @@ var WorkerSession = class {
3209
3450
  try {
3210
3451
  await this.close();
3211
3452
  } catch (err) {
3212
- import_log12.log.catch(err, {}, {
3453
+ import_log13.log.catch(err, {}, {
3213
3454
  file: "worker-session.ts",
3214
3455
  line: 137,
3215
3456
  scope: this,
@@ -3220,7 +3461,7 @@ var WorkerSession = class {
3220
3461
  }, this._options.heartbeatInterval);
3221
3462
  }
3222
3463
  async close() {
3223
- import_log12.log.info("closing..", {}, {
3464
+ import_log13.log.info("closing..", {}, {
3224
3465
  file: "worker-session.ts",
3225
3466
  line: 144,
3226
3467
  scope: this,
@@ -3229,7 +3470,7 @@ var WorkerSession = class {
3229
3470
  try {
3230
3471
  await this.onClose.callIfSet();
3231
3472
  } catch (err) {
3232
- import_log12.log.catch(err, {}, {
3473
+ import_log13.log.catch(err, {}, {
3233
3474
  file: "worker-session.ts",
3234
3475
  line: 148,
3235
3476
  scope: this,
@@ -3248,7 +3489,7 @@ var WorkerSession = class {
3248
3489
  try {
3249
3490
  await (0, import_async16.asyncTimeout)(this._shellClientRpc.open(), 1e3);
3250
3491
  } catch (e) {
3251
- import_log12.log.info("No shell connected.", {}, {
3492
+ import_log13.log.info("No shell connected.", {}, {
3252
3493
  file: "worker-session.ts",
3253
3494
  line: 162,
3254
3495
  scope: this,
@@ -3257,8 +3498,8 @@ var WorkerSession = class {
3257
3498
  }
3258
3499
  }
3259
3500
  };
3260
- __decorate4([
3261
- import_log12.logInfo
3501
+ __decorate5([
3502
+ import_log13.logInfo
3262
3503
  ], WorkerSession.prototype, "origin", void 0);
3263
3504
 
3264
3505
  // packages/sdk/client-services/src/packlets/services/service-context.ts
@@ -3268,7 +3509,7 @@ var import_debug6 = require("@dxos/debug");
3268
3509
  var import_echo_pipeline4 = require("@dxos/echo-pipeline");
3269
3510
  var import_feed_store4 = require("@dxos/feed-store");
3270
3511
  var import_keyring = require("@dxos/keyring");
3271
- var import_log14 = require("@dxos/log");
3512
+ var import_log15 = require("@dxos/log");
3272
3513
  var ServiceContext = class {
3273
3514
  // prettier-ignore
3274
3515
  constructor(storage, networkManager, modelFactory) {
@@ -3305,7 +3546,7 @@ var ServiceContext = class {
3305
3546
  });
3306
3547
  }
3307
3548
  async open() {
3308
- (0, import_log14.log)("opening...", {}, {
3549
+ (0, import_log15.log)("opening...", {}, {
3309
3550
  file: "service-context.ts",
3310
3551
  line: 94,
3311
3552
  scope: this,
@@ -3317,7 +3558,7 @@ var ServiceContext = class {
3317
3558
  if (this.identityManager.identity) {
3318
3559
  await this._initialize();
3319
3560
  }
3320
- (0, import_log14.log)("opened", {}, {
3561
+ (0, import_log15.log)("opened", {}, {
3321
3562
  file: "service-context.ts",
3322
3563
  line: 101,
3323
3564
  scope: this,
@@ -3326,7 +3567,7 @@ var ServiceContext = class {
3326
3567
  }
3327
3568
  async close() {
3328
3569
  var _a, _b;
3329
- (0, import_log14.log)("closing...", {}, {
3570
+ (0, import_log15.log)("closing...", {}, {
3330
3571
  file: "service-context.ts",
3331
3572
  line: 105,
3332
3573
  scope: this,
@@ -3339,7 +3580,7 @@ var ServiceContext = class {
3339
3580
  await this.feedStore.close();
3340
3581
  await this.networkManager.close();
3341
3582
  this.dataServiceSubscriptions.clear();
3342
- (0, import_log14.log)("closed", {}, {
3583
+ (0, import_log15.log)("closed", {}, {
3343
3584
  file: "service-context.ts",
3344
3585
  line: 113,
3345
3586
  scope: this,
@@ -3347,7 +3588,7 @@ var ServiceContext = class {
3347
3588
  });
3348
3589
  }
3349
3590
  async reset() {
3350
- (0, import_log14.log)("resetting...", {}, {
3591
+ (0, import_log15.log)("resetting...", {}, {
3351
3592
  file: "service-context.ts",
3352
3593
  line: 117,
3353
3594
  scope: this,
@@ -3355,7 +3596,7 @@ var ServiceContext = class {
3355
3596
  });
3356
3597
  await this.close();
3357
3598
  await this.storage.reset();
3358
- (0, import_log14.log)("reset", {}, {
3599
+ (0, import_log15.log)("reset", {}, {
3359
3600
  file: "service-context.ts",
3360
3601
  line: 120,
3361
3602
  scope: this,
@@ -3375,7 +3616,7 @@ var ServiceContext = class {
3375
3616
  // Called when identity is created.
3376
3617
  async _initialize() {
3377
3618
  var _a;
3378
- (0, import_log14.log)("initializing spaces...", {}, {
3619
+ (0, import_log15.log)("initializing spaces...", {}, {
3379
3620
  file: "service-context.ts",
3380
3621
  line: 139,
3381
3622
  scope: this,
@@ -3409,7 +3650,7 @@ var ServiceContext = class {
3409
3650
  return;
3410
3651
  }
3411
3652
  if (!this.dataSpaceManager) {
3412
- (0, import_log14.log)("dataSpaceManager not initialized yet, ignoring space admission", {
3653
+ (0, import_log15.log)("dataSpaceManager not initialized yet, ignoring space admission", {
3413
3654
  details: assertion
3414
3655
  }, {
3415
3656
  file: "service-context.ts",
@@ -3420,7 +3661,7 @@ var ServiceContext = class {
3420
3661
  return;
3421
3662
  }
3422
3663
  if (this.dataSpaceManager.spaces.has(assertion.spaceKey)) {
3423
- (0, import_log14.log)("space already exists, ignoring space admission", {
3664
+ (0, import_log15.log)("space already exists, ignoring space admission", {
3424
3665
  details: assertion
3425
3666
  }, {
3426
3667
  file: "service-context.ts",
@@ -3431,7 +3672,7 @@ var ServiceContext = class {
3431
3672
  return;
3432
3673
  }
3433
3674
  try {
3434
- (0, import_log14.log)("accepting space recorded in halo", {
3675
+ (0, import_log15.log)("accepting space recorded in halo", {
3435
3676
  details: assertion
3436
3677
  }, {
3437
3678
  file: "service-context.ts",
@@ -3444,7 +3685,7 @@ var ServiceContext = class {
3444
3685
  genesisFeedKey: assertion.genesisFeedKey
3445
3686
  });
3446
3687
  } catch (err) {
3447
- import_log14.log.catch(err, {}, {
3688
+ import_log15.log.catch(err, {}, {
3448
3689
  file: "service-context.ts",
3449
3690
  line: 197,
3450
3691
  scope: this,
@@ -3485,7 +3726,7 @@ var ServiceRegistry = class {
3485
3726
  var ClientServicesHost = class {
3486
3727
  constructor({
3487
3728
  config,
3488
- modelFactory = (0, import_client6.createDefaultModelFactory)(),
3729
+ modelFactory = (0, import_client8.createDefaultModelFactory)(),
3489
3730
  // TODO(burdon): Create ApolloLink abstraction (see Client).
3490
3731
  networkManager,
3491
3732
  storage,
@@ -3493,6 +3734,7 @@ var ClientServicesHost = class {
3493
3734
  lockKey
3494
3735
  } = {}) {
3495
3736
  this._statusUpdate = new import_async19.Event();
3737
+ this._opening = false;
3496
3738
  this._open = false;
3497
3739
  this._storage = storage;
3498
3740
  this._modelFactory = modelFactory;
@@ -3504,7 +3746,9 @@ var ClientServicesHost = class {
3504
3746
  }
3505
3747
  this._resourceLock = lockKey ? new VaultResourceLock({
3506
3748
  lockKey,
3507
- onAcquire: () => this.open(),
3749
+ onAcquire: () => {
3750
+ this._opening || this.open();
3751
+ },
3508
3752
  onRelease: () => this.close()
3509
3753
  }) : void 0;
3510
3754
  this._systemService = new SystemServiceImpl({
@@ -3524,7 +3768,7 @@ var ClientServicesHost = class {
3524
3768
  await this._serviceContext.reset();
3525
3769
  }
3526
3770
  });
3527
- this._serviceRegistry = new ServiceRegistry(import_client6.clientServiceBundle, {
3771
+ this._serviceRegistry = new ServiceRegistry(import_client8.clientServiceBundle, {
3528
3772
  SystemService: this._systemService
3529
3773
  });
3530
3774
  }
@@ -3560,20 +3804,23 @@ var ClientServicesHost = class {
3560
3804
  }
3561
3805
  }
3562
3806
  async open() {
3563
- var _a, _b;
3807
+ var _a, _b, _c;
3564
3808
  if (this._open) {
3565
3809
  return;
3566
3810
  }
3567
3811
  (0, import_node_assert12.default)(this._config, "config not set");
3568
3812
  (0, import_node_assert12.default)(this._storage, "storage not set");
3569
3813
  (0, import_node_assert12.default)(this._networkManager, "network manager not set");
3570
- (0, import_log15.log)("opening...", {}, {
3814
+ this._opening = true;
3815
+ (0, import_log16.log)("opening...", {
3816
+ lockKey: (_a = this._resourceLock) == null ? void 0 : _a.lockKey
3817
+ }, {
3571
3818
  file: "service-host.ts",
3572
- line: 166,
3819
+ line: 170,
3573
3820
  scope: this,
3574
3821
  callSite: (f, a) => f(...a)
3575
3822
  });
3576
- await ((_a = this._resourceLock) == null ? void 0 : _a.acquire());
3823
+ await ((_b = this._resourceLock) == null ? void 0 : _b.acquire());
3577
3824
  this._serviceContext = new ServiceContext(this._storage, this._networkManager, this._modelFactory);
3578
3825
  this._serviceRegistry.setServices({
3579
3826
  SystemService: this._systemService,
@@ -3602,14 +3849,15 @@ var ClientServicesHost = class {
3602
3849
  })
3603
3850
  });
3604
3851
  await this._serviceContext.open();
3852
+ this._opening = false;
3605
3853
  this._open = true;
3606
3854
  this._statusUpdate.emit();
3607
- const deviceKey = (_b = this._serviceContext.identityManager.identity) == null ? void 0 : _b.deviceKey;
3608
- (0, import_log15.log)("opened", {
3855
+ const deviceKey = (_c = this._serviceContext.identityManager.identity) == null ? void 0 : _c.deviceKey;
3856
+ (0, import_log16.log)("opened", {
3609
3857
  deviceKey
3610
3858
  }, {
3611
3859
  file: "service-host.ts",
3612
- line: 219,
3860
+ line: 224,
3613
3861
  scope: this,
3614
3862
  callSite: (f, a) => f(...a)
3615
3863
  });
@@ -3620,11 +3868,11 @@ var ClientServicesHost = class {
3620
3868
  return;
3621
3869
  }
3622
3870
  const deviceKey = (_a = this._serviceContext.identityManager.identity) == null ? void 0 : _a.deviceKey;
3623
- (0, import_log15.log)("closing...", {
3871
+ (0, import_log16.log)("closing...", {
3624
3872
  deviceKey
3625
3873
  }, {
3626
3874
  file: "service-host.ts",
3627
- line: 228,
3875
+ line: 233,
3628
3876
  scope: this,
3629
3877
  callSite: (f, a) => f(...a)
3630
3878
  });
@@ -3634,11 +3882,11 @@ var ClientServicesHost = class {
3634
3882
  await this._serviceContext.close();
3635
3883
  this._open = false;
3636
3884
  this._statusUpdate.emit();
3637
- (0, import_log15.log)("closed", {
3885
+ (0, import_log16.log)("closed", {
3638
3886
  deviceKey
3639
3887
  }, {
3640
3888
  file: "service-host.ts",
3641
- line: 233,
3889
+ line: 238,
3642
3890
  scope: this,
3643
3891
  callSite: (f, a) => f(...a)
3644
3892
  });
@@ -3669,7 +3917,7 @@ var LocalClientServices = class {
3669
3917
 
3670
3918
  // packages/sdk/client-services/src/packlets/services/utils.ts
3671
3919
  var import_config2 = require("@dxos/config");
3672
- var import_log16 = require("@dxos/log");
3920
+ var import_log17 = require("@dxos/log");
3673
3921
  var import_messaging3 = require("@dxos/messaging");
3674
3922
  var import_network_manager6 = require("@dxos/network-manager");
3675
3923
 
@@ -3691,7 +3939,7 @@ var createServiceContext = ({ signalContext = new import_messaging4.MemorySignal
3691
3939
  signalManager: new import_messaging4.MemorySignalManager(signalContext),
3692
3940
  transportFactory: import_network_manager7.MemoryTransportFactory
3693
3941
  });
3694
- const modelFactory = (0, import_client7.createDefaultModelFactory)();
3942
+ const modelFactory = (0, import_client9.createDefaultModelFactory)();
3695
3943
  return new ServiceContext(storage, networkManager, modelFactory);
3696
3944
  };
3697
3945
  var createPeers = async (numPeers) => {
@@ -3831,11 +4079,13 @@ var performInvitation = async (host, guest, context) => {
3831
4079
  // packages/sdk/client-services/src/packlets/testing/test-builder.ts
3832
4080
  var import_node_assert14 = __toESM(require("node:assert"));
3833
4081
  var import_async21 = require("@dxos/async");
3834
- var import_client8 = require("@dxos/client");
4082
+ var import_client10 = require("@dxos/client");
3835
4083
  var import_config3 = require("@dxos/config");
4084
+ var import_debug9 = require("@dxos/debug");
3836
4085
  var import_document_model = require("@dxos/document-model");
3837
4086
  var import_echo_db = require("@dxos/echo-db");
3838
4087
  var import_keys10 = require("@dxos/keys");
4088
+ var import_log18 = require("@dxos/log");
3839
4089
  var import_messaging5 = require("@dxos/messaging");
3840
4090
  var import_network_manager8 = require("@dxos/network-manager");
3841
4091
  var import_rpc5 = require("@dxos/rpc");
@@ -3852,7 +4102,7 @@ var testConfigWithLocalSignal = new import_config3.Config({
3852
4102
  });
3853
4103
  var TestBuilder = class {
3854
4104
  // prettier-ignore
3855
- constructor(config, _modelFactory = (0, import_client8.createDefaultModelFactory)(), _signalManagerContext = new import_messaging5.MemorySignalManagerContext()) {
4105
+ constructor(config, _modelFactory = (0, import_client10.createDefaultModelFactory)(), _signalManagerContext = new import_messaging5.MemorySignalManagerContext()) {
3856
4106
  this._modelFactory = _modelFactory;
3857
4107
  this._signalManagerContext = _signalManagerContext;
3858
4108
  this._config = config != null ? config : new import_config3.Config();
@@ -3914,8 +4164,8 @@ var TestBuilder = class {
3914
4164
  handlers: host.services,
3915
4165
  port: hostPort
3916
4166
  });
3917
- const client = new import_client8.Client({
3918
- services: new import_client8.ClientServicesProxy(proxyPort)
4167
+ const client = new import_client10.Client({
4168
+ services: new import_client10.ClientServicesProxy(proxyPort)
3919
4169
  });
3920
4170
  return [
3921
4171
  client,
@@ -3926,15 +4176,70 @@ var TestBuilder = class {
3926
4176
  var testSpace = async (create, check = create) => {
3927
4177
  const objectId = import_keys10.PublicKey.random().toHex();
3928
4178
  const result = create.mutate((0, import_echo_db.genesisMutation)(objectId, import_document_model.DocumentModel.meta.type));
3929
- await result.getReceipt();
3930
- (0, import_node_assert14.default)(create._itemManager.entities.has(result.objectsCreated[0].id));
3931
- await (0, import_async21.asyncTimeout)(check._itemManager.update.waitForCondition(() => check._itemManager.entities.has(objectId)), 1e3);
4179
+ await result.batch.getReceipt();
4180
+ (0, import_node_assert14.default)(create._itemManager.entities.has(result.objectsUpdated[0].id));
4181
+ await (0, import_async21.asyncTimeout)(check.itemUpdate.waitForCondition(() => check._itemManager.entities.has(objectId)), 1e3);
3932
4182
  return result;
3933
4183
  };
3934
4184
  var syncItems = async (db1, db2) => {
3935
4185
  await testSpace(db1, db2);
3936
4186
  await testSpace(db2, db1);
3937
4187
  };
4188
+ var joinCommonSpace = async ([initialPeer, ...peers], spaceKey) => {
4189
+ const rootSpace = spaceKey ? initialPeer.getSpace(spaceKey) : await initialPeer.createSpace();
4190
+ (0, import_node_assert14.default)(rootSpace, "Space not found.");
4191
+ await Promise.all(peers.map(async (peer) => {
4192
+ const hostDone = new import_async21.Trigger();
4193
+ const guestDone = new import_async21.Trigger();
4194
+ const hostObservabli = rootSpace.createInvitation({
4195
+ type: import_client10.Invitation.Type.INTERACTIVE_TESTING
4196
+ });
4197
+ (0, import_log18.log)("invitation created", {}, {
4198
+ file: "test-builder.ts",
4199
+ line: 154,
4200
+ scope: void 0,
4201
+ callSite: (f, a) => f(...a)
4202
+ });
4203
+ hostObservabli.subscribe({
4204
+ onConnecting: (invitation) => {
4205
+ const guestObservable = peer.acceptInvitation(invitation);
4206
+ (0, import_log18.log)("invitation accepted", {}, {
4207
+ file: "test-builder.ts",
4208
+ line: 158,
4209
+ scope: void 0,
4210
+ callSite: (f, a) => f(...a)
4211
+ });
4212
+ guestObservable.subscribe({
4213
+ onSuccess: (invitation2) => {
4214
+ guestDone.wake(invitation2);
4215
+ (0, import_log18.log)("invitation guestDone", {}, {
4216
+ file: "test-builder.ts",
4217
+ line: 163,
4218
+ scope: void 0,
4219
+ callSite: (f, a) => f(...a)
4220
+ });
4221
+ },
4222
+ onError: (err) => (0, import_debug9.raise)(err)
4223
+ });
4224
+ },
4225
+ onSuccess: (invitation) => {
4226
+ hostDone.wake(invitation);
4227
+ (0, import_log18.log)("invitation hostDone", {}, {
4228
+ file: "test-builder.ts",
4229
+ line: 170,
4230
+ scope: void 0,
4231
+ callSite: (f, a) => f(...a)
4232
+ });
4233
+ },
4234
+ onError: (err) => (0, import_debug9.raise)(err)
4235
+ });
4236
+ await Promise.all([
4237
+ hostDone.wait(),
4238
+ guestDone.wait()
4239
+ ]);
4240
+ }));
4241
+ return rootSpace.key;
4242
+ };
3938
4243
  // Annotate the CommonJS export names for ESM import in node:
3939
4244
  0 && (module.exports = {
3940
4245
  HostTestBuilder,
@@ -3946,6 +4251,7 @@ var syncItems = async (db1, db2) => {
3946
4251
  createServiceContext,
3947
4252
  createServiceHost,
3948
4253
  createSigningContext,
4254
+ joinCommonSpace,
3949
4255
  performInvitation,
3950
4256
  syncItems,
3951
4257
  syncItemsLocal,