@dxos/echo-db 2.33.4-dev.faf06c70 → 2.33.5-dev.1fc05a51

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 (199) hide show
  1. package/dist/src/api/selection/queries.d.ts.map +1 -1
  2. package/dist/src/api/selection/queries.js +13 -17
  3. package/dist/src/api/selection/queries.js.map +1 -1
  4. package/dist/src/api/selection/selection.d.ts.map +1 -1
  5. package/dist/src/api/selection/selection.js +1 -3
  6. package/dist/src/api/selection/selection.js.map +1 -1
  7. package/dist/src/api/selection/selection.test.js +4 -12
  8. package/dist/src/api/selection/selection.test.js.map +1 -1
  9. package/dist/src/database/item-demuxer.d.ts +1 -1
  10. package/dist/src/database/item-demuxer.d.ts.map +1 -1
  11. package/dist/src/database/item-demuxer.js +3 -5
  12. package/dist/src/database/item-demuxer.js.map +1 -1
  13. package/dist/src/database/item-manager.js +2 -2
  14. package/dist/src/database/item-manager.js.map +1 -1
  15. package/dist/src/database/testing.js +1 -1
  16. package/dist/src/database/testing.js.map +1 -1
  17. package/dist/src/echo.d.ts +5 -12
  18. package/dist/src/echo.d.ts.map +1 -1
  19. package/dist/src/echo.js +9 -20
  20. package/dist/src/echo.js.map +1 -1
  21. package/dist/src/halo/halo-factory.d.ts.map +1 -1
  22. package/dist/src/halo/halo-factory.js +5 -11
  23. package/dist/src/halo/halo-factory.js.map +1 -1
  24. package/dist/src/halo/halo-party.d.ts +3 -3
  25. package/dist/src/halo/halo-party.d.ts.map +1 -1
  26. package/dist/src/halo/halo-party.js +6 -4
  27. package/dist/src/halo/halo-party.js.map +1 -1
  28. package/dist/src/halo/halo.test.js +5 -4
  29. package/dist/src/halo/halo.test.js.map +1 -1
  30. package/dist/src/halo/identity.js +2 -2
  31. package/dist/src/halo/identity.js.map +1 -1
  32. package/dist/src/halo/party-opener.d.ts +1 -1
  33. package/dist/src/halo/party-opener.d.ts.map +1 -1
  34. package/dist/src/halo/party-opener.js +2 -2
  35. package/dist/src/halo/party-opener.js.map +1 -1
  36. package/dist/src/halo/preferences.d.ts.map +1 -1
  37. package/dist/src/halo/preferences.js +7 -10
  38. package/dist/src/halo/preferences.js.map +1 -1
  39. package/dist/src/index.d.ts +0 -1
  40. package/dist/src/index.d.ts.map +1 -1
  41. package/dist/src/index.js +0 -1
  42. package/dist/src/index.js.map +1 -1
  43. package/dist/src/invitations/greeting-protocol-provider.d.ts.map +1 -1
  44. package/dist/src/invitations/greeting-protocol-provider.js +5 -9
  45. package/dist/src/invitations/greeting-protocol-provider.js.map +1 -1
  46. package/dist/src/invitations/greeting-responder.d.ts +2 -2
  47. package/dist/src/invitations/greeting-responder.d.ts.map +1 -1
  48. package/dist/src/invitations/greeting-responder.js +8 -12
  49. package/dist/src/invitations/greeting-responder.js.map +1 -1
  50. package/dist/src/invitations/invitation-factory.d.ts +2 -2
  51. package/dist/src/invitations/invitation-factory.d.ts.map +1 -1
  52. package/dist/src/invitations/invitation-factory.js.map +1 -1
  53. package/dist/src/invitations/offline-invitation-claimer.d.ts.map +1 -1
  54. package/dist/src/invitations/offline-invitation-claimer.js +5 -7
  55. package/dist/src/invitations/offline-invitation-claimer.js.map +1 -1
  56. package/dist/src/parties/data-party.d.ts +7 -5
  57. package/dist/src/parties/data-party.d.ts.map +1 -1
  58. package/dist/src/parties/data-party.js +12 -9
  59. package/dist/src/parties/data-party.js.map +1 -1
  60. package/dist/src/parties/data-party.test.js +16 -16
  61. package/dist/src/parties/data-party.test.js.map +1 -1
  62. package/dist/src/parties/party-factory.d.ts +0 -6
  63. package/dist/src/parties/party-factory.d.ts.map +1 -1
  64. package/dist/src/parties/party-factory.js +17 -45
  65. package/dist/src/parties/party-factory.js.map +1 -1
  66. package/dist/src/parties/party-manager.d.ts.map +1 -1
  67. package/dist/src/parties/party-manager.js +2 -1
  68. package/dist/src/parties/party-manager.js.map +1 -1
  69. package/dist/src/parties/party-manager.test.js +7 -7
  70. package/dist/src/parties/party-manager.test.js.map +1 -1
  71. package/dist/src/pipeline/message-selector.d.ts +2 -2
  72. package/dist/src/pipeline/message-selector.d.ts.map +1 -1
  73. package/dist/src/pipeline/message-selector.js +29 -39
  74. package/dist/src/pipeline/message-selector.js.map +1 -1
  75. package/dist/src/pipeline/metadata-store.d.ts +3 -3
  76. package/dist/src/pipeline/metadata-store.d.ts.map +1 -1
  77. package/dist/src/pipeline/metadata-store.js +5 -5
  78. package/dist/src/pipeline/metadata-store.js.map +1 -1
  79. package/dist/src/pipeline/metadata-store.test.js +9 -5
  80. package/dist/src/pipeline/metadata-store.test.js.map +1 -1
  81. package/dist/src/pipeline/party-core.d.ts +3 -2
  82. package/dist/src/pipeline/party-core.d.ts.map +1 -1
  83. package/dist/src/pipeline/party-core.js +5 -0
  84. package/dist/src/pipeline/party-core.js.map +1 -1
  85. package/dist/src/pipeline/party-core.test.js +17 -43
  86. package/dist/src/pipeline/party-core.test.js.map +1 -1
  87. package/dist/src/pipeline/party-processor.d.ts +23 -5
  88. package/dist/src/pipeline/party-processor.d.ts.map +1 -1
  89. package/dist/src/pipeline/party-processor.js.map +1 -1
  90. package/dist/src/pipeline/pipeline.d.ts +2 -4
  91. package/dist/src/pipeline/pipeline.d.ts.map +1 -1
  92. package/dist/src/pipeline/pipeline.js +0 -3
  93. package/dist/src/pipeline/pipeline.js.map +1 -1
  94. package/dist/src/pipeline/pipeline.test.js +2 -2
  95. package/dist/src/pipeline/pipeline.test.js.map +1 -1
  96. package/dist/src/protocol/auth-plugin.d.ts +1 -1
  97. package/dist/src/protocol/auth-plugin.d.ts.map +1 -1
  98. package/dist/src/protocol/auth-plugin.js +1 -3
  99. package/dist/src/protocol/auth-plugin.js.map +1 -1
  100. package/dist/src/protocol/authenticator.d.ts +2 -2
  101. package/dist/src/protocol/authenticator.d.ts.map +1 -1
  102. package/dist/src/protocol/authenticator.js +12 -16
  103. package/dist/src/protocol/authenticator.js.map +1 -1
  104. package/dist/src/protocol/halo-recovery-plugin.d.ts +1 -1
  105. package/dist/src/protocol/halo-recovery-plugin.d.ts.map +1 -1
  106. package/dist/src/protocol/halo-recovery-plugin.js +1 -3
  107. package/dist/src/protocol/halo-recovery-plugin.js.map +1 -1
  108. package/dist/src/protocol/identity-credentials.d.ts +2 -2
  109. package/dist/src/protocol/identity-credentials.d.ts.map +1 -1
  110. package/dist/src/protocol/identity-credentials.js +4 -4
  111. package/dist/src/protocol/identity-credentials.js.map +1 -1
  112. package/dist/src/protocol/offline-invitation-plugin.d.ts +1 -1
  113. package/dist/src/protocol/offline-invitation-plugin.d.ts.map +1 -1
  114. package/dist/src/protocol/offline-invitation-plugin.js +1 -3
  115. package/dist/src/protocol/offline-invitation-plugin.js.map +1 -1
  116. package/dist/src/protocol/party-protocol-factory.d.ts +1 -14
  117. package/dist/src/protocol/party-protocol-factory.d.ts.map +1 -1
  118. package/dist/src/protocol/party-protocol-factory.js +2 -55
  119. package/dist/src/protocol/party-protocol-factory.js.map +1 -1
  120. package/dist/src/protocol/replicator-plugin.d.ts +7 -0
  121. package/dist/src/protocol/replicator-plugin.d.ts.map +1 -0
  122. package/dist/src/protocol/replicator-plugin.js +36 -0
  123. package/dist/src/protocol/replicator-plugin.js.map +1 -0
  124. package/dist/src/snapshots/snapshot-generator.d.ts +1 -1
  125. package/dist/src/snapshots/snapshot-generator.d.ts.map +1 -1
  126. package/dist/src/snapshots/snapshot-generator.js +13 -15
  127. package/dist/src/snapshots/snapshot-generator.js.map +1 -1
  128. package/dist/src/snapshots/snapshot-store.d.ts +3 -3
  129. package/dist/src/snapshots/snapshot-store.d.ts.map +1 -1
  130. package/dist/src/snapshots/snapshot-store.js +5 -5
  131. package/dist/src/snapshots/snapshot-store.js.map +1 -1
  132. package/dist/src/snapshots/snapshot-store.test.js +2 -2
  133. package/dist/src/snapshots/snapshot-store.test.js.map +1 -1
  134. package/dist/src/testing/benchmark.test.d.ts +2 -0
  135. package/dist/src/testing/benchmark.test.d.ts.map +1 -0
  136. package/dist/src/testing/benchmark.test.js +25 -0
  137. package/dist/src/testing/benchmark.test.js.map +1 -0
  138. package/dist/src/testing/testing-factories.js +2 -2
  139. package/dist/src/testing/testing-factories.js.map +1 -1
  140. package/dist/src/testing/testing.d.ts +3 -4
  141. package/dist/src/testing/testing.d.ts.map +1 -1
  142. package/dist/src/testing/testing.js +3 -4
  143. package/dist/src/testing/testing.js.map +1 -1
  144. package/dist/tsconfig.tsbuildinfo +1 -1
  145. package/package.json +21 -21
  146. package/src/api/selection/queries.ts +14 -18
  147. package/src/api/selection/selection.test.ts +4 -12
  148. package/src/api/selection/selection.ts +1 -7
  149. package/src/database/item-demuxer.ts +2 -4
  150. package/src/database/item-manager.ts +2 -2
  151. package/src/database/testing.ts +1 -1
  152. package/src/echo.ts +13 -35
  153. package/src/halo/halo-factory.ts +6 -18
  154. package/src/halo/halo-party.ts +8 -7
  155. package/src/halo/halo.test.ts +5 -4
  156. package/src/halo/identity.ts +2 -2
  157. package/src/halo/party-opener.ts +2 -2
  158. package/src/halo/preferences.ts +7 -10
  159. package/src/index.ts +0 -1
  160. package/src/invitations/greeting-protocol-provider.ts +5 -9
  161. package/src/invitations/greeting-responder.ts +10 -14
  162. package/src/invitations/invitation-factory.ts +2 -2
  163. package/src/invitations/offline-invitation-claimer.ts +5 -7
  164. package/src/parties/data-party.test.ts +17 -16
  165. package/src/parties/data-party.ts +17 -13
  166. package/src/parties/party-factory.ts +23 -69
  167. package/src/parties/party-manager.test.ts +9 -7
  168. package/src/parties/party-manager.ts +2 -1
  169. package/src/pipeline/message-selector.ts +31 -44
  170. package/src/pipeline/metadata-store.test.ts +9 -5
  171. package/src/pipeline/metadata-store.ts +5 -5
  172. package/src/pipeline/party-core.test.ts +19 -60
  173. package/src/pipeline/party-core.ts +7 -2
  174. package/src/pipeline/party-processor.ts +26 -2
  175. package/src/pipeline/pipeline.test.ts +2 -2
  176. package/src/pipeline/pipeline.ts +2 -6
  177. package/src/protocol/auth-plugin.ts +1 -3
  178. package/src/protocol/authenticator.ts +27 -31
  179. package/src/protocol/halo-recovery-plugin.ts +4 -6
  180. package/src/protocol/identity-credentials.ts +4 -4
  181. package/src/protocol/offline-invitation-plugin.ts +4 -6
  182. package/src/protocol/party-protocol-factory.ts +3 -56
  183. package/src/protocol/replicator-plugin.ts +37 -0
  184. package/src/snapshots/snapshot-generator.ts +12 -16
  185. package/src/snapshots/snapshot-store.test.ts +2 -2
  186. package/src/snapshots/snapshot-store.ts +5 -6
  187. package/src/testing/benchmark.test.ts +30 -0
  188. package/src/testing/testing-factories.ts +2 -2
  189. package/src/testing/testing.ts +4 -8
  190. package/dist/src/util/index.d.ts +0 -2
  191. package/dist/src/util/index.d.ts.map +0 -1
  192. package/dist/src/util/index.js +0 -17
  193. package/dist/src/util/index.js.map +0 -1
  194. package/dist/src/util/persistant-ram-storage.d.ts +0 -6
  195. package/dist/src/util/persistant-ram-storage.d.ts.map +0 -1
  196. package/dist/src/util/persistant-ram-storage.js +0 -32
  197. package/dist/src/util/persistant-ram-storage.js.map +0 -1
  198. package/src/util/index.ts +0 -5
  199. package/src/util/persistant-ram-storage.ts +0 -33
@@ -5,10 +5,11 @@
5
5
  import assert from 'assert';
6
6
 
7
7
  import { synchronized, Event } from '@dxos/async';
8
- import { KeyHint } from '@dxos/credentials';
8
+ import { KeyHint, Message as HaloMessage } from '@dxos/credentials';
9
9
  import { PublicKey } from '@dxos/crypto';
10
10
  import { timed } from '@dxos/debug';
11
- import { PartyKey, PartySnapshot, Timeframe } from '@dxos/echo-protocol';
11
+ import { PartyKey, PartySnapshot, Timeframe, WriteReceipt } from '@dxos/echo-protocol';
12
+ import { FeedDescriptor } from '@dxos/feed-store';
12
13
  import { ModelFactory } from '@dxos/model-factory';
13
14
  import { NetworkManager } from '@dxos/network-manager';
14
15
  import { ObjectModel } from '@dxos/object-model';
@@ -19,6 +20,7 @@ import { InvitationFactory } from '../invitations';
19
20
  import { PartyFeedProvider, PartyProtocolFactory, PartyCore, PartyOptions } from '../pipeline';
20
21
  import { createAuthPlugin, createOfflineInvitationPlugin, createAuthenticator, createCredentialsProvider } from '../protocol';
21
22
  import { CredentialsSigner } from '../protocol/credentials-signer';
23
+ import { createReplicatorPlugin } from '../protocol/replicator-plugin';
22
24
  import { SnapshotStore } from '../snapshots';
23
25
  import { CONTACT_DEBOUNCE_INTERVAL } from './party-manager';
24
26
 
@@ -125,16 +127,6 @@ export class DataParty {
125
127
  return this._invitationManager;
126
128
  }
127
129
 
128
- // TODO(burdon): Remove?
129
- get feedProvider (): PartyFeedProvider {
130
- return this._feedProvider;
131
- }
132
-
133
- get preferences (): PartyPreferences {
134
- assert(this._preferences, 'Preferences not available.');
135
- return this._preferences;
136
- }
137
-
138
130
  get title () {
139
131
  return this._preferences?.getLastKnownTitle();
140
132
  }
@@ -173,12 +165,12 @@ export class DataParty {
173
165
  this._protocol = new PartyProtocolFactory(
174
166
  this._partyCore.key,
175
167
  this._networkManager,
176
- this._feedProvider,
177
168
  deviceKey.publicKey,
178
169
  createCredentialsProvider(this._credentialsSigner, this._partyCore.key, writeFeed.key)
179
170
  );
180
171
 
181
172
  await this._protocol.start([
173
+ createReplicatorPlugin(this._feedProvider),
182
174
  createAuthPlugin(createAuthenticator(this._partyCore.processor, this._credentialsSigner), deviceKey.publicKey),
183
175
  createOfflineInvitationPlugin(this._invitationManager, deviceKey.publicKey)
184
176
  ]);
@@ -210,6 +202,18 @@ export class DataParty {
210
202
  return this;
211
203
  }
212
204
 
205
+ async getWriteFeed (): Promise<FeedDescriptor> {
206
+ return this._feedProvider.createOrOpenWritableFeed();
207
+ }
208
+
209
+ getFeeds (): FeedDescriptor[] {
210
+ return this._feedProvider.getFeeds();
211
+ }
212
+
213
+ writeCredentialsMessage (message: HaloMessage): Promise<WriteReceipt> {
214
+ return this._partyCore.writeCredentialsMessage(message);
215
+ }
216
+
213
217
  get isActive (): boolean {
214
218
  assert(this._preferences, 'PartyActivator required');
215
219
  return this._preferences.isActive;
@@ -60,10 +60,10 @@ export class PartyFactory {
60
60
  // Connect the pipeline.
61
61
  await party.open();
62
62
 
63
- const writableFeed = await party.feedProvider.createOrOpenWritableFeed();
63
+ const writableFeed = await party.getWriteFeed();
64
64
 
65
65
  // PartyGenesis (self-signed by Party).
66
- await party.processor.writeHaloMessage(createPartyGenesisMessage(
66
+ await party.writeCredentialsMessage(createPartyGenesisMessage(
67
67
  identity.keyring,
68
68
  partyKey,
69
69
  writableFeed.key,
@@ -71,7 +71,7 @@ export class PartyFactory {
71
71
  );
72
72
 
73
73
  // KeyAdmit (IdentityGenesis in an Envelope signed by Party).
74
- await party.processor.writeHaloMessage(createEnvelopeMessage(
74
+ await party.writeCredentialsMessage(createEnvelopeMessage(
75
75
  identity.keyring,
76
76
  partyKey.publicKey,
77
77
  wrapMessage(identity.identityGenesis),
@@ -80,7 +80,7 @@ export class PartyFactory {
80
80
 
81
81
  // FeedAdmit (signed by the Device KeyChain).
82
82
  // TODO(dmaretskyi): Is this really needed since a feed is already admitted by party genesis message.
83
- await party.processor.writeHaloMessage(createFeedAdmitMessage(
83
+ await party.writeCredentialsMessage(createFeedAdmitMessage(
84
84
  identity.keyring,
85
85
  partyKey.publicKey,
86
86
  writableFeed.key,
@@ -89,7 +89,7 @@ export class PartyFactory {
89
89
 
90
90
  // IdentityInfo in an Envelope signed by the Device KeyChain.
91
91
  if (identity.identityInfo) {
92
- await party.processor.writeHaloMessage(createEnvelopeMessage(
92
+ await party.writeCredentialsMessage(createEnvelopeMessage(
93
93
  identity.keyring,
94
94
  partyKey.publicKey,
95
95
  wrapMessage(identity.identityInfo),
@@ -106,50 +106,6 @@ export class PartyFactory {
106
106
  return party;
107
107
  }
108
108
 
109
- /**
110
- * Constructs a party object and creates a local write feed for it.
111
- * @param partyKey
112
- * @param hints
113
- */
114
- async addParty (partyKey: PartyKey, hints: KeyHint[] = []) {
115
- const identity = this._identityProvider() ?? raise(new IdentityNotInitializedError());
116
-
117
- /*
118
- * TODO(telackey): We shouldn't have to add our key here, it should be in the hints, but our hint
119
- * mechanism is broken by not waiting on the messages to be processed before returning.
120
- */
121
-
122
- const feedProvider = this._feedProviderFactory(partyKey);
123
- const { feed } = await feedProvider.createOrOpenWritableFeed();
124
- const feedKeyPair = identity.keyring.getKey(feed.key);
125
- assert(feedKeyPair, 'Keypair for writable feed not found.');
126
- const party = new DataParty(
127
- partyKey,
128
- this._modelFactory,
129
- this._snapshotStore,
130
- feedProvider,
131
- identity.createCredentialsSigner(),
132
- identity.preferences,
133
- this._networkManager,
134
- hints,
135
- undefined,
136
- this._options
137
- );
138
-
139
- await party.open();
140
- const isHalo = identity.identityKey.publicKey.equals(partyKey);
141
- const signingKey = isHalo ? identity.deviceKey : identity.deviceKeyChain;
142
- assert(signingKey, 'No device key or keychain.');
143
- // Write the Feed genesis message.
144
- await party.processor.writeHaloMessage(createFeedAdmitMessage(
145
- identity.keyring,
146
- partyKey,
147
- feedKeyPair.publicKey,
148
- [signingKey]
149
- ));
150
- return party;
151
- }
152
-
153
109
  /**
154
110
  * Constructs a party object from an existing set of feeds.
155
111
  * @param partyKey
@@ -190,7 +146,6 @@ export class PartyFactory {
190
146
  }
191
147
 
192
148
  async joinParty (invitationDescriptor: InvitationDescriptor, secretProvider: SecretProvider): Promise<DataParty> {
193
- const haloInvitation = !!invitationDescriptor.identityKey;
194
149
  const originalInvitation = invitationDescriptor;
195
150
 
196
151
  const identity = this._identityProvider() ?? raise(new IdentityNotInitializedError());
@@ -218,19 +173,18 @@ export class PartyFactory {
218
173
 
219
174
  await initiator.connect();
220
175
  const { partyKey, hints } = await initiator.redeemInvitation(secretProvider);
221
- const party = await this.addParty(partyKey, hints);
176
+ const party = await this.constructParty(partyKey, hints);
177
+ await party.open();
222
178
  await initiator.destroy();
223
- if (!haloInvitation) {
224
- // Copy our signed IdentityInfo into the new Party.
225
- const infoMessage = identity.identityInfo;
226
- if (infoMessage) {
227
- await party.processor.writeHaloMessage(createEnvelopeMessage(
228
- identity.keyring,
229
- partyKey,
230
- wrapMessage(infoMessage),
231
- [identity.deviceKeyChain]
232
- ));
233
- }
179
+
180
+ // Copy our signed IdentityInfo into the new Party.
181
+ if (identity.identityInfo) {
182
+ await party.writeCredentialsMessage(createEnvelopeMessage(
183
+ identity.keyring,
184
+ partyKey,
185
+ wrapMessage(identity.identityInfo),
186
+ [identity.deviceKeyChain]
187
+ ));
234
188
  }
235
189
 
236
190
  return party;
@@ -247,10 +201,10 @@ export class PartyFactory {
247
201
  // Connect the pipeline.
248
202
  await party.open();
249
203
 
250
- const writableFeed = await party.feedProvider.createOrOpenWritableFeed();
204
+ const writableFeed = await party.getWriteFeed();
251
205
 
252
206
  // PartyGenesis (self-signed by Party).
253
- await party.processor.writeHaloMessage(createPartyGenesisMessage(
207
+ await party.writeCredentialsMessage(createPartyGenesisMessage(
254
208
  identity.keyring,
255
209
  partyKey,
256
210
  writableFeed.key,
@@ -258,7 +212,7 @@ export class PartyFactory {
258
212
  );
259
213
 
260
214
  // KeyAdmit (IdentityGenesis in an Envelope signed by Party).
261
- await party.processor.writeHaloMessage(createEnvelopeMessage(
215
+ await party.writeCredentialsMessage(createEnvelopeMessage(
262
216
  identity.keyring,
263
217
  partyKey.publicKey,
264
218
  wrapMessage(identity.identityGenesis),
@@ -266,7 +220,7 @@ export class PartyFactory {
266
220
  ));
267
221
 
268
222
  // FeedAdmit (signed by the Device KeyChain).
269
- await party.processor.writeHaloMessage(createFeedAdmitMessage(
223
+ await party.writeCredentialsMessage(createFeedAdmitMessage(
270
224
  identity.keyring,
271
225
  partyKey.publicKey,
272
226
  writableFeed.key,
@@ -275,7 +229,7 @@ export class PartyFactory {
275
229
 
276
230
  // IdentityInfo in an Envelope signed by the Device KeyChain.
277
231
  if (identity.identityInfo) {
278
- await party.processor.writeHaloMessage(createEnvelopeMessage(
232
+ await party.writeCredentialsMessage(createEnvelopeMessage(
279
233
  identity.keyring,
280
234
  partyKey.publicKey,
281
235
  wrapMessage(identity.identityInfo),
@@ -285,7 +239,7 @@ export class PartyFactory {
285
239
 
286
240
  // const keyAdmitMessage = snapshot.halo?.messages?.[1];
287
241
  // assert(keyAdmitMessage);
288
- // await party.processor.writeHaloMessage(createEnvelopeMessage(
242
+ // await party.writeCredentialsMessage(createEnvelopeMessage(
289
243
  // identity.signer,
290
244
  // partyKey.publicKey,
291
245
  // keyAdmitMessage,
@@ -293,7 +247,7 @@ export class PartyFactory {
293
247
  // ));
294
248
 
295
249
  // for(const message of snapshot.halo?.messages?.slice(2) || []) {
296
- // await party.processor.writeHaloMessage(message);
250
+ // await party.writeCredentialsMessage(message);
297
251
  // }
298
252
 
299
253
  // Write messages to create ECHO items.
@@ -38,7 +38,6 @@ import { MetadataStore, PartyFeedProvider } from '../pipeline';
38
38
  import { createTestIdentityCredentials } from '../protocol/identity-credentials';
39
39
  import { SnapshotStore } from '../snapshots';
40
40
  import { messageLogger } from '../testing';
41
- import { createRamStorage } from '../util';
42
41
  import { PARTY_ITEM_TYPE } from './data-party';
43
42
  import { PartyFactory } from './party-factory';
44
43
  import { PartyManager } from './party-manager';
@@ -56,9 +55,11 @@ const log = debug('dxos:echo:parties:party-manager:test');
56
55
  */
57
56
  const setup = async () => {
58
57
  const keyring = new Keyring();
59
- const metadataStore = new MetadataStore(createRamStorage());
60
- const feedStore = new FeedStore(createStorage('', StorageType.RAM), { valueEncoding: codec });
61
- const snapshotStore = new SnapshotStore(createStorage('', StorageType.RAM));
58
+
59
+ const storage = createStorage('', StorageType.RAM);
60
+ const snapshotStore = new SnapshotStore(storage.directory('snapshots'));
61
+ const metadataStore = new MetadataStore(storage.directory('metadata'));
62
+ const feedStore = new FeedStore(storage.directory('feed'), { valueEncoding: codec });
62
63
  const modelFactory = new ModelFactory().registerModel(ObjectModel);
63
64
  const networkManager = new NetworkManager();
64
65
  const feedProviderFactory = (partyKey: PublicKey) => new PartyFeedProvider(metadataStore, keyring, feedStore, partyKey);
@@ -148,12 +149,13 @@ describe('Party manager', () => {
148
149
  });
149
150
 
150
151
  test('Create from cold start', async () => {
152
+
151
153
  const storage = createStorage('', StorageType.RAM);
152
- const feedStore = new FeedStore(storage, { valueEncoding: codec });
154
+ const feedStore = new FeedStore(storage.directory('feed'), { valueEncoding: codec });
153
155
  const keyring = new Keyring();
154
- const metadataStore = new MetadataStore(createRamStorage());
156
+ const snapshotStore = new SnapshotStore(storage.directory('snapshots'));
157
+ const metadataStore = new MetadataStore(storage.directory('metadata'));
155
158
  const modelFactory = new ModelFactory().registerModel(ObjectModel);
156
- const snapshotStore = new SnapshotStore(createStorage('', StorageType.RAM));
157
159
  const networkManager = new NetworkManager();
158
160
  const feedProviderFactory = (partyKey: PublicKey) => new PartyFeedProvider(metadataStore, keyring, feedStore, partyKey);
159
161
 
@@ -175,7 +175,8 @@ export class PartyManager {
175
175
  }
176
176
 
177
177
  log(`Adding party partyKey=${partyKey.toHex()} hints=${hints.length}`);
178
- const party = await this._partyFactory.addParty(partyKey, hints);
178
+ const party = await this._partyFactory.constructParty(partyKey, hints);
179
+ await party.open();
179
180
  await this._metadataStore.addParty(party.key);
180
181
  this._setParty(party);
181
182
  return party;
@@ -5,12 +5,12 @@
5
5
  import assert from 'assert';
6
6
  import debug from 'debug';
7
7
 
8
- import { Keyring, getPartyCredentialMessageType, PartyCredential, admitsKeys } from '@dxos/credentials';
8
+ import { getPartyCredentialMessageType, PartyCredential } from '@dxos/credentials';
9
9
  import { PublicKey } from '@dxos/crypto';
10
10
  import { MessageSelector } from '@dxos/echo-protocol';
11
11
 
12
12
  import { TimeframeClock } from '../database';
13
- import { PartyProcessor } from './party-processor';
13
+ import { PartyStateProvider } from './party-processor';
14
14
 
15
15
  const log = debug('dxos:echo-db:message-selector');
16
16
 
@@ -23,56 +23,43 @@ const log = debug('dxos:echo-db:message-selector');
23
23
  * @param partyProcessor
24
24
  * @param timeframeClock
25
25
  */
26
- export function createMessageSelector (
27
- partyProcessor: PartyProcessor,
28
- timeframeClock: TimeframeClock
29
- ): MessageSelector {
30
- // TODO(telackey): Add KeyAdmit checks.
31
- return candidates => {
32
- // Check ECHO message candidates first since they are less expensive than HALO cancidates.
33
- for (let i = 0; i < candidates.length; i++) {
34
- const { data: { echo } } = candidates[i];
35
- const feedKey = PublicKey.from(candidates[i].key);
36
- if (!echo) {
37
- continue;
38
- }
26
+ export const createMessageSelector = (partyProcessor: PartyStateProvider, timeframeClock: TimeframeClock): MessageSelector => candidates => {
27
+ // Check ECHO message candidates first since they are less expensive than HALO cancidates.
28
+ for (let i = 0; i < candidates.length; i++) {
29
+ const { data: { echo } } = candidates[i];
30
+ const feedKey = PublicKey.from(candidates[i].key);
31
+ if (!echo) {
32
+ continue;
33
+ }
39
34
 
40
- assert(echo.timeframe);
41
- if (partyProcessor.isFeedAdmitted(feedKey) && !timeframeClock.hasGaps(echo.timeframe)) {
42
- return i;
43
- }
35
+ assert(echo.timeframe);
36
+ if (partyProcessor.isFeedAdmitted(feedKey) && !timeframeClock.hasGaps(echo.timeframe)) {
37
+ return i;
44
38
  }
39
+ }
45
40
 
46
- // Check HALO message candidates.
47
- for (let i = 0; i < candidates.length; i++) {
48
- const { data: { halo } } = candidates[i];
49
- const feedKey = PublicKey.from(candidates[i].key);
50
- if (!halo) {
51
- continue;
52
- }
41
+ // Check HALO message candidates.
42
+ for (let i = 0; i < candidates.length; i++) {
43
+ const { data: { halo } } = candidates[i];
44
+ const feedKey = PublicKey.from(candidates[i].key);
45
+ if (!halo) {
46
+ continue;
47
+ }
53
48
 
54
- if (partyProcessor.isFeedAdmitted(feedKey)) {
55
- return i;
56
- }
49
+ if (partyProcessor.isFeedAdmitted(feedKey)) {
50
+ return i;
51
+ }
57
52
 
58
- if (partyProcessor.genesisRequired) {
53
+ if (partyProcessor.genesisRequired) {
54
+ try { // TODO(dmaretskyi): Get getPartyCredentialMessageType crashes for some reason.
59
55
  // TODO(telackey): Add check that this is for the right Party.
60
56
  if (getPartyCredentialMessageType(halo) === PartyCredential.Type.PARTY_GENESIS) {
61
57
  return i;
62
58
  }
63
- } else if (getPartyCredentialMessageType(halo) === PartyCredential.Type.FEED_ADMIT) {
64
- if (admitsKeys(halo).find(key => key.equals(feedKey))) {
65
- // TODO(marik-d): Calling `Keyring.signingKeys` is expensive. Is there any way to optimize/cache this?
66
- for (const signedBy of Keyring.signingKeys(halo)) {
67
- if (partyProcessor.isMemberKey(signedBy) || signedBy.equals(partyProcessor.partyKey)) {
68
- return i;
69
- }
70
- }
71
- }
72
- }
59
+ } catch { }
73
60
  }
61
+ }
74
62
 
75
- // Not ready for this message yet.
76
- log('Skipping...');
77
- };
78
- }
63
+ // Not ready for this message yet.
64
+ log('Skipping...');
65
+ };
@@ -5,13 +5,14 @@
5
5
  import expect from 'expect';
6
6
 
7
7
  import { PublicKey } from '@dxos/crypto';
8
+ import { createStorage, StorageType } from '@dxos/random-access-multi-storage';
8
9
 
9
- import { createRamStorage } from '../util';
10
10
  import { MetadataStore } from './metadata-store';
11
11
 
12
12
  describe('MetadataStore in-memory', () => {
13
13
  it('Creates party and adds feeds to it', async () => {
14
- const store = new MetadataStore(createRamStorage());
14
+ const storage = createStorage('', StorageType.RAM);
15
+ const store = new MetadataStore(storage.directory('metadata'));
15
16
  await store.load();
16
17
  expect(store.parties?.length).toBe(0);
17
18
 
@@ -33,7 +34,8 @@ describe('MetadataStore in-memory', () => {
33
34
  });
34
35
 
35
36
  it('Creates party when adding feed', async () => {
36
- const store = new MetadataStore(createRamStorage());
37
+ const storage = createStorage('', StorageType.RAM);
38
+ const store = new MetadataStore(storage.directory('metadata'));
37
39
  await store.load();
38
40
 
39
41
  const partyKey = PublicKey.random();
@@ -45,7 +47,8 @@ describe('MetadataStore in-memory', () => {
45
47
  });
46
48
 
47
49
  it('Doesn\'t add same feed twice', async () => {
48
- const store = new MetadataStore(createRamStorage());
50
+ const storage = createStorage('', StorageType.RAM);
51
+ const store = new MetadataStore(storage.directory('metadata'));
49
52
  await store.load();
50
53
 
51
54
  const partyKey = PublicKey.random();
@@ -60,7 +63,8 @@ describe('MetadataStore in-memory', () => {
60
63
 
61
64
  // TODO(yivlad): Doesn't work for now.
62
65
  it.skip('Resets storage', async () => {
63
- const store = new MetadataStore(createRamStorage());
66
+ const storage = createStorage('snapshots', StorageType.RAM);
67
+ const store = new MetadataStore(storage.directory(''));
64
68
 
65
69
  const partyKey = PublicKey.random();
66
70
  const feedKey = PublicKey.random();
@@ -8,7 +8,7 @@ import debug from 'debug';
8
8
  import { PublicKey } from '@dxos/crypto';
9
9
  import { failUndefined } from '@dxos/debug';
10
10
  import { EchoMetadata, PartyMetadata, schema } from '@dxos/echo-protocol';
11
- import { IStorage } from '@dxos/random-access-multi-storage';
11
+ import { Directory } from '@dxos/random-access-multi-storage';
12
12
 
13
13
  /**
14
14
  * Version for the schema of the stored data as defined in dxos.echo.metadata.EchoMetadata.
@@ -28,7 +28,7 @@ export class MetadataStore {
28
28
  };
29
29
 
30
30
  constructor (
31
- private readonly _storage: IStorage
31
+ private readonly _directory: Directory
32
32
  ) {}
33
33
 
34
34
  get version (): number {
@@ -47,7 +47,7 @@ export class MetadataStore {
47
47
  * Loads metadata from persistent storage.
48
48
  */
49
49
  async load (): Promise<void> {
50
- const file = this._storage.createOrOpen('EchoMetadata');
50
+ const file = this._directory.createOrOpen('EchoMetadata');
51
51
  try {
52
52
  const { size } = await file.stat();
53
53
  if (size === 0) {
@@ -75,7 +75,7 @@ export class MetadataStore {
75
75
  updated: new Date()
76
76
  };
77
77
 
78
- const file = this._storage.createOrOpen('EchoMetadata');
78
+ const file = this._directory.createOrOpen('EchoMetadata');
79
79
 
80
80
  try {
81
81
  const encoded = Buffer.from(schema.getCodecForType('dxos.echo.metadata.EchoMetadata').encode(data));
@@ -90,7 +90,7 @@ export class MetadataStore {
90
90
  */
91
91
  async clear (): Promise<void> {
92
92
  log('Clearing all echo metadata...');
93
- await this._storage.destroy();
93
+ await this._directory.destroy();
94
94
  }
95
95
 
96
96
  /**
@@ -16,23 +16,23 @@ import { ObjectModel } from '@dxos/object-model';
16
16
  import { createStorage, StorageType } from '@dxos/random-access-multi-storage';
17
17
  import { afterTest } from '@dxos/testutils';
18
18
 
19
- import { MetadataStore, PartyFeedProvider, ReplicatorProtocolPluginFactory } from '../pipeline';
19
+ import { MetadataStore, PartyFeedProvider } from '../pipeline';
20
+ import { createReplicatorPlugin } from '../protocol/replicator-plugin';
20
21
  import { SnapshotStore } from '../snapshots';
21
- import { createRamStorage } from '../util';
22
22
  import { PartyCore } from './party-core';
23
23
 
24
24
  describe('PartyCore', () => {
25
25
  const setup = async () => {
26
26
  const storage = createStorage('', StorageType.RAM);
27
- const feedStore = new FeedStore(storage, { valueEncoding: codec });
27
+ const feedStore = new FeedStore(storage.directory('feed'), { valueEncoding: codec });
28
28
  afterTest(async () => feedStore.close());
29
29
 
30
30
  const keyring = new Keyring();
31
31
 
32
- const metadataStore = new MetadataStore(createRamStorage());
32
+ const metadataStore = new MetadataStore(storage.directory('metadata'));
33
33
 
34
34
  const modelFactory = new ModelFactory().registerModel(ObjectModel);
35
- const snapshotStore = new SnapshotStore(createStorage('', StorageType.RAM));
35
+ const snapshotStore = new SnapshotStore(storage.directory('snapshots'));
36
36
 
37
37
  const partyKey = await keyring.createKeyRecord({ type: KeyType.PARTY });
38
38
 
@@ -51,7 +51,7 @@ describe('PartyCore', () => {
51
51
  afterTest(async () => party.close());
52
52
 
53
53
  // PartyGenesis (self-signed by Party).
54
- await party.processor.writeHaloMessage(createPartyGenesisMessage(
54
+ await party.writeCredentialsMessage(createPartyGenesisMessage(
55
55
  keyring,
56
56
  partyKey,
57
57
  feed.key,
@@ -59,7 +59,7 @@ describe('PartyCore', () => {
59
59
  );
60
60
 
61
61
  // FeedAdmit (signed by the Device KeyChain).
62
- await party.processor.writeHaloMessage(createFeedAdmitMessage(
62
+ await party.writeCredentialsMessage(createFeedAdmitMessage(
63
63
  keyring,
64
64
  partyKey.publicKey,
65
65
  feed.key,
@@ -120,7 +120,7 @@ describe('PartyCore', () => {
120
120
  const feedKey = await keyring.createKeyRecord({ type: KeyType.FEED });
121
121
 
122
122
  const eventFired = feedStore.feedOpenedEvent.waitForCount(1);
123
- await party.processor.writeHaloMessage(createFeedAdmitMessage(
123
+ await party.writeCredentialsMessage(createFeedAdmitMessage(
124
124
  keyring,
125
125
  party.key,
126
126
  feedKey.publicKey,
@@ -132,15 +132,15 @@ describe('PartyCore', () => {
132
132
 
133
133
  test('opens feed from hints', async () => {
134
134
  const storage = createStorage('', StorageType.RAM);
135
- const feedStore = new FeedStore(storage, { valueEncoding: codec });
135
+ const feedStore = new FeedStore(storage.directory('feed'), { valueEncoding: codec });
136
136
  afterTest(async () => feedStore.close());
137
137
 
138
138
  const keyring = new Keyring();
139
139
 
140
- const metadataStore = new MetadataStore(createRamStorage());
140
+ const metadataStore = new MetadataStore(storage.directory('metadata'));
141
141
 
142
142
  const modelFactory = new ModelFactory().registerModel(ObjectModel);
143
- const snapshotStore = new SnapshotStore(createStorage('', StorageType.RAM));
143
+ const snapshotStore = new SnapshotStore(storage.directory('snapshots'));
144
144
 
145
145
  const partyKey = await keyring.createKeyRecord({ type: KeyType.PARTY });
146
146
 
@@ -197,7 +197,7 @@ describe('PartyCore', () => {
197
197
  const fullKey = keyring.getFullKey(feedKey.publicKey);
198
198
  const feed2 = await feedStore.openReadWriteFeed(fullKey!.publicKey, fullKey!.secretKey!);
199
199
 
200
- await party.processor.writeHaloMessage(createFeedAdmitMessage(
200
+ await party.writeCredentialsMessage(createFeedAdmitMessage(
201
201
  keyring,
202
202
  party.key,
203
203
  feed2.key,
@@ -226,7 +226,7 @@ describe('PartyCore', () => {
226
226
  const feedKey = await keyring.createKeyRecord({ type: KeyType.FEED });
227
227
  const fullKey = keyring.getFullKey(feedKey.publicKey);
228
228
 
229
- await party.processor.writeHaloMessage(createFeedAdmitMessage(
229
+ await party.writeCredentialsMessage(createFeedAdmitMessage(
230
230
  keyring,
231
231
  party.key,
232
232
  feedKey.publicKey,
@@ -249,54 +249,17 @@ describe('PartyCore', () => {
249
249
  await promiseTimeout(party.database.waitForItem({ id: itemId }), 1000, new Error('timeout'));
250
250
  });
251
251
 
252
- test('self-admitting feed with a hint', async () => {
253
- const { party, keyring, partyKey, feedStore } = await setup();
254
- await party.open();
255
-
256
- const feedKey = await keyring.createKeyRecord({ type: KeyType.FEED });
257
- const fullKey = keyring.getFullKey(feedKey.publicKey);
258
- const feed2 = await feedStore.openReadWriteFeed(fullKey!.publicKey, fullKey!.secretKey!);
259
-
260
- await party.processor.takeHints([{
261
- type: KeyType.FEED,
262
- publicKey: feedKey.publicKey
263
- }]);
264
-
265
- await feed2.append({
266
- halo: createFeedAdmitMessage(
267
- keyring,
268
- party.key,
269
- feedKey.publicKey,
270
- [partyKey]
271
- )
272
- });
273
-
274
- const itemId = createId();
275
- await feed2.append({
276
- echo: {
277
- itemId,
278
- genesis: {
279
- itemType: 'dxos:example',
280
- modelType: ObjectModel.meta.type
281
- },
282
- timeframe: new Timeframe()
283
- }
284
- });
285
-
286
- await promiseTimeout(party.database.waitForItem({ id: itemId }), 1000, new Error('timeout'));
287
- });
288
-
289
252
  test('two instances replicating', async () => {
290
253
  const peer1 = await setup();
291
254
 
292
255
  const storage = createStorage('', StorageType.RAM);
293
- const feedStore = new FeedStore(storage, { valueEncoding: codec });
256
+ const feedStore = new FeedStore(storage.directory('feed'), { valueEncoding: codec });
294
257
  afterTest(async () => feedStore.close());
295
258
 
296
- const metadataStore = new MetadataStore(createRamStorage());
259
+ const metadataStore = new MetadataStore(storage.directory('metadata'));
297
260
 
298
261
  const modelFactory = new ModelFactory().registerModel(ObjectModel);
299
- const snapshotStore = new SnapshotStore(createStorage('', StorageType.RAM));
262
+ const snapshotStore = new SnapshotStore(storage.directory('snapshots'));
300
263
 
301
264
  const partyFeedProvider = new PartyFeedProvider(metadataStore, peer1.keyring, feedStore, peer1.party.key);
302
265
 
@@ -310,7 +273,7 @@ describe('PartyCore', () => {
310
273
 
311
274
  const feed2 = await partyFeedProvider.createOrOpenWritableFeed();
312
275
 
313
- await peer1.party.processor.writeHaloMessage(createFeedAdmitMessage(
276
+ await peer1.party.writeCredentialsMessage(createFeedAdmitMessage(
314
277
  peer1.keyring,
315
278
  peer1.party.key,
316
279
  feed2.key,
@@ -324,12 +287,8 @@ describe('PartyCore', () => {
324
287
  afterTest(async () => party2.close());
325
288
 
326
289
  createTestProtocolPair(
327
- new ReplicatorProtocolPluginFactory(
328
- peer1.partyFeedProvider
329
- ).createPlugins().map(r => r.createExtension()),
330
- new ReplicatorProtocolPluginFactory(
331
- partyFeedProvider
332
- ).createPlugins().map(r => r.createExtension())
290
+ [createReplicatorPlugin(peer1.partyFeedProvider).createExtension()],
291
+ [createReplicatorPlugin(partyFeedProvider).createExtension()]
333
292
  );
334
293
 
335
294
  const item1 = await peer1.party.database.createItem();