@dxos/echo-db 2.33.1-dev.d6c55789 → 2.33.1-dev.e48632f8

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 (53) hide show
  1. package/dist/src/database/data-mirror.js +2 -2
  2. package/dist/src/database/data-mirror.js.map +1 -1
  3. package/dist/src/database/item-demuxer.test.js +2 -2
  4. package/dist/src/database/item-demuxer.test.js.map +1 -1
  5. package/dist/src/echo.d.ts +19 -19
  6. package/dist/src/echo.d.ts.map +1 -1
  7. package/dist/src/echo.js +32 -19
  8. package/dist/src/echo.js.map +1 -1
  9. package/dist/src/echo.test.js +1 -1
  10. package/dist/src/echo.test.js.map +1 -1
  11. package/dist/src/parties/party-core.d.ts.map +1 -1
  12. package/dist/src/parties/party-core.js +7 -3
  13. package/dist/src/parties/party-core.js.map +1 -1
  14. package/dist/src/parties/party-core.test.js +136 -5
  15. package/dist/src/parties/party-core.test.js.map +1 -1
  16. package/dist/src/parties/party-internal.d.ts.map +1 -1
  17. package/dist/src/parties/party-internal.js +15 -10
  18. package/dist/src/parties/party-internal.js.map +1 -1
  19. package/dist/src/parties/party-manager.test.js +4 -4
  20. package/dist/src/parties/party-manager.test.js.map +1 -1
  21. package/dist/src/pipeline/party-processor.d.ts +1 -1
  22. package/dist/src/pipeline/party-processor.d.ts.map +1 -1
  23. package/dist/src/pipeline/party-processor.js +3 -3
  24. package/dist/src/pipeline/party-processor.js.map +1 -1
  25. package/dist/src/pipeline/party-processor.test.js +8 -8
  26. package/dist/src/pipeline/party-processor.test.js.map +1 -1
  27. package/dist/src/pipeline/party-protocol-factory.d.ts +11 -0
  28. package/dist/src/pipeline/party-protocol-factory.d.ts.map +1 -1
  29. package/dist/src/pipeline/party-protocol-factory.js +2 -1
  30. package/dist/src/pipeline/party-protocol-factory.js.map +1 -1
  31. package/dist/src/pipeline/pipeline.js +1 -1
  32. package/dist/src/pipeline/pipeline.js.map +1 -1
  33. package/dist/src/pipeline/pipeline.test.js +3 -3
  34. package/dist/src/pipeline/pipeline.test.js.map +1 -1
  35. package/dist/src/util/persistant-ram-storage.d.ts.map +1 -1
  36. package/dist/src/util/persistant-ram-storage.js +1 -1
  37. package/dist/src/util/persistant-ram-storage.js.map +1 -1
  38. package/dist/tsconfig.tsbuildinfo +1 -1
  39. package/package.json +17 -17
  40. package/src/database/data-mirror.ts +2 -2
  41. package/src/database/item-demuxer.test.ts +3 -3
  42. package/src/echo.test.ts +1 -1
  43. package/src/echo.ts +76 -73
  44. package/src/parties/party-core.test.ts +233 -10
  45. package/src/parties/party-core.ts +8 -3
  46. package/src/parties/party-internal.ts +14 -9
  47. package/src/parties/party-manager.test.ts +5 -5
  48. package/src/pipeline/party-processor.test.ts +8 -8
  49. package/src/pipeline/party-processor.ts +3 -3
  50. package/src/pipeline/party-protocol-factory.ts +1 -1
  51. package/src/pipeline/pipeline.test.ts +4 -4
  52. package/src/pipeline/pipeline.ts +1 -1
  53. package/src/util/persistant-ram-storage.ts +3 -3
package/src/echo.ts CHANGED
@@ -6,6 +6,7 @@ import assert from 'assert';
6
6
  import debug from 'debug';
7
7
  import memdown from 'memdown';
8
8
 
9
+ import { synchronized } from '@dxos/async';
9
10
  import { Keyring, KeyStore, SecretProvider } from '@dxos/credentials';
10
11
  import { PublicKey } from '@dxos/crypto';
11
12
  import { InvalidStateError } from '@dxos/debug';
@@ -237,6 +238,7 @@ export class ECHO {
237
238
  *
238
239
  * Previously active parties will be opened and will begin replication.
239
240
  */
241
+ @synchronized
240
242
  async open (onProgressCallback?: ((progress: OpenProgress) => void) | undefined) {
241
243
  if (this.isOpen) {
242
244
  return;
@@ -258,6 +260,7 @@ export class ECHO {
258
260
  /**
259
261
  * Closes the ECHO instance.
260
262
  */
263
+ @synchronized
261
264
  async close () {
262
265
  if (!this.isOpen) {
263
266
  return;
@@ -276,107 +279,107 @@ export class ECHO {
276
279
  await this.networkManager.destroy();
277
280
  }
278
281
 
279
- /**
282
+ /**
280
283
  * Removes all data and closes this ECHO instance.
281
284
  *
282
285
  * The instance will be in an unusable state at this point and a page refresh is recommended.
283
286
  */
284
- // TODO(burdon): Enable re-open.
285
- async reset () {
286
- await this.close();
287
-
288
- try {
289
- if (this._feedStore.storage.destroy) {
290
- await this._feedStore.storage.destroy();
291
- }
292
- } catch (err: any) {
293
- error('Error clearing feed storage:', err);
294
- }
295
-
296
- await this.halo.reset();
297
-
298
- try {
299
- await this._snapshotStore.clear();
300
- } catch (err: any) {
301
- error('Error clearing snapshot storage:', err);
302
- }
303
-
304
- try {
305
- await this._metadataStore.clear();
306
- } catch (err: any) {
307
- error('Error clearing metadata storage:', err);
308
- }
309
- }
310
-
311
- //
312
- // Parties.
313
- //
314
-
315
- /**
287
+ // TODO(burdon): Enable re-open.
288
+ async reset () {
289
+ await this.close();
290
+
291
+ try {
292
+ if (this._feedStore.storage.destroy) {
293
+ await this._feedStore.storage.destroy();
294
+ }
295
+ } catch (err: any) {
296
+ error('Error clearing feed storage:', err);
297
+ }
298
+
299
+ await this.halo.reset();
300
+
301
+ try {
302
+ await this._snapshotStore.clear();
303
+ } catch (err: any) {
304
+ error('Error clearing snapshot storage:', err);
305
+ }
306
+
307
+ try {
308
+ await this._metadataStore.clear();
309
+ } catch (err: any) {
310
+ error('Error clearing metadata storage:', err);
311
+ }
312
+ }
313
+
314
+ //
315
+ // Parties.
316
+ //
317
+
318
+ /**
316
319
  * Creates a new party.
317
320
  */
318
- async createParty (): Promise<PartyInternal> {
319
- await this.open();
321
+ async createParty (): Promise<PartyInternal> {
322
+ await this.open();
320
323
 
321
- const party = await this._partyManager.createParty();
322
- await party.open();
324
+ const party = await this._partyManager.createParty();
325
+ await party.open();
323
326
 
324
- return party;
325
- }
327
+ return party;
328
+ }
326
329
 
327
- /**
330
+ /**
328
331
  * Clones an existing party from a snapshot.
329
332
  * @param snapshot
330
333
  */
331
- async cloneParty (snapshot: PartySnapshot) {
332
- await this.open();
334
+ async cloneParty (snapshot: PartySnapshot) {
335
+ await this.open();
333
336
 
334
- const party = await this._partyManager.cloneParty(snapshot);
335
- await party.open();
337
+ const party = await this._partyManager.cloneParty(snapshot);
338
+ await party.open();
336
339
 
337
- return party;
338
- }
340
+ return party;
341
+ }
339
342
 
340
- /**
343
+ /**
341
344
  * Returns an individual party by it's key.
342
345
  * @param {PartyKey} partyKey
343
346
  */
344
- getParty (partyKey: PartyKey): PartyInternal | undefined {
345
- if (!this._partyManager.isOpen) {
346
- throw new InvalidStateError();
347
- }
347
+ getParty (partyKey: PartyKey): PartyInternal | undefined {
348
+ if (!this._partyManager.isOpen) {
349
+ throw new InvalidStateError();
350
+ }
348
351
 
349
- const party = this._partyManager.parties.find(party => party.key.equals(partyKey));
350
- return party;
351
- }
352
+ const party = this._partyManager.parties.find(party => party.key.equals(partyKey));
353
+ return party;
354
+ }
352
355
 
353
- /**
356
+ /**
354
357
  * Queries for a set of Parties matching the optional filter.
355
358
  * @param {PartyFilter} filter
356
359
  */
357
- // eslint-disable-next-line unused-imports/no-unused-vars
358
- queryParties (filter?: PartyFilter): ResultSet<PartyInternal> {
359
- if (!this._partyManager.isOpen) {
360
- throw new InvalidStateError();
361
- }
362
-
363
- return new ResultSet(
364
- this._partyManager.update.discardParameter(),
365
- () => this._partyManager.parties
366
- );
367
- }
368
-
369
- /**
360
+ // eslint-disable-next-line unused-imports/no-unused-vars
361
+ queryParties (filter?: PartyFilter): ResultSet<PartyInternal> {
362
+ if (!this._partyManager.isOpen) {
363
+ throw new InvalidStateError();
364
+ }
365
+
366
+ return new ResultSet(
367
+ this._partyManager.update.discardParameter(),
368
+ () => this._partyManager.parties
369
+ );
370
+ }
371
+
372
+ /**
370
373
  * Joins a party that was created by another peer and starts replicating with it.
371
374
  * @param invitationDescriptor Invitation descriptor passed from another peer.
372
375
  * @param secretProvider Shared secret provider, the other peer creating the invitation must have the same secret.
373
376
  */
374
- async joinParty (invitationDescriptor: InvitationDescriptor, secretProvider?: SecretProvider): Promise<PartyInternal> {
375
- assert(this._partyManager.isOpen, new InvalidStateError());
377
+ async joinParty (invitationDescriptor: InvitationDescriptor, secretProvider?: SecretProvider): Promise<PartyInternal> {
378
+ assert(this._partyManager.isOpen, new InvalidStateError());
376
379
 
377
- const actualSecretProvider =
380
+ const actualSecretProvider =
378
381
  secretProvider ?? OfflineInvitationClaimer.createSecretProvider(this.halo.identity);
379
382
 
380
- return this._partyManager.joinParty(invitationDescriptor, actualSecretProvider);
381
- }
383
+ return this._partyManager.joinParty(invitationDescriptor, actualSecretProvider);
384
+ }
382
385
  }
@@ -5,24 +5,26 @@
5
5
  import expect from 'expect';
6
6
  import { it as test } from 'mocha';
7
7
 
8
+ import { promiseTimeout } from '@dxos/async';
8
9
  import { createFeedAdmitMessage, createPartyGenesisMessage, Keyring, KeyType } from '@dxos/credentials';
9
- import { PublicKey } from '@dxos/crypto';
10
- import { codec } from '@dxos/echo-protocol';
10
+ import { createId, PublicKey } from '@dxos/crypto';
11
+ import { codec, Timeframe } from '@dxos/echo-protocol';
11
12
  import { FeedStore } from '@dxos/feed-store';
13
+ import { createTestProtocolPair } from '@dxos/mesh-protocol';
12
14
  import { ModelFactory } from '@dxos/model-factory';
13
15
  import { ObjectModel } from '@dxos/object-model';
14
- import { createStorage, STORAGE_RAM } from '@dxos/random-access-multi-storage';
16
+ import { createStorage, StorageType } from '@dxos/random-access-multi-storage';
15
17
  import { afterTest } from '@dxos/testutils';
16
18
 
17
19
  import { MetadataStore } from '../metadata';
18
- import { PartyFeedProvider } from '../pipeline';
20
+ import { PartyFeedProvider, ReplicatorProtocolPluginFactory } from '../pipeline';
19
21
  import { SnapshotStore } from '../snapshots';
20
22
  import { createRamStorage } from '../util';
21
23
  import { PartyCore } from './party-core';
22
24
 
23
25
  describe('PartyCore', () => {
24
26
  const setup = async () => {
25
- const storage = createStorage('', STORAGE_RAM);
27
+ const storage = createStorage('', StorageType.RAM);
26
28
  const feedStore = new FeedStore(storage, { valueEncoding: codec });
27
29
  afterTest(async () => feedStore.close());
28
30
 
@@ -31,7 +33,7 @@ describe('PartyCore', () => {
31
33
  const metadataStore = new MetadataStore(createRamStorage());
32
34
 
33
35
  const modelFactory = new ModelFactory().registerModel(ObjectModel);
34
- const snapshotStore = new SnapshotStore(createStorage('', STORAGE_RAM));
36
+ const snapshotStore = new SnapshotStore(createStorage('', StorageType.RAM));
35
37
 
36
38
  const partyKey = await keyring.createKeyRecord({ type: KeyType.PARTY });
37
39
 
@@ -65,10 +67,7 @@ describe('PartyCore', () => {
65
67
  [partyKey]
66
68
  ));
67
69
 
68
- // The Party key is an inception key; its SecretKey must be destroyed once the Party has been created.
69
- await keyring.deleteSecretKey(partyKey);
70
-
71
- return { party, feedKey: feed.key, feed, feedStore };
70
+ return { party, feedKey: feed.key, feed, feedStore, partyKey, keyring, partyFeedProvider };
72
71
  };
73
72
 
74
73
  test('create & have the feed key admitted', async () => {
@@ -115,4 +114,228 @@ describe('PartyCore', () => {
115
114
  expect(parent.children).toContain(child);
116
115
  }
117
116
  });
117
+
118
+ test('feed admit message triggers new feed to be opened', async () => {
119
+ const { party, partyKey, keyring, partyFeedProvider, feedStore } = await setup();
120
+
121
+ const feedKey = await keyring.createKeyRecord({ type: KeyType.FEED });
122
+
123
+ const eventFired = feedStore.feedOpenedEvent.waitForCount(1);
124
+ await party.processor.writeHaloMessage(createFeedAdmitMessage(
125
+ keyring,
126
+ party.key,
127
+ feedKey.publicKey,
128
+ [partyKey]
129
+ ));
130
+ await promiseTimeout(eventFired, 1000, new Error('timeout'));
131
+ expect(partyFeedProvider.getFeeds().find(k => k.key.equals(feedKey.publicKey))).toBeTruthy();
132
+ });
133
+
134
+ test('opens feed from hints', async () => {
135
+ const storage = createStorage('', StorageType.RAM);
136
+ const feedStore = new FeedStore(storage, { valueEncoding: codec });
137
+ afterTest(async () => feedStore.close());
138
+
139
+ const keyring = new Keyring();
140
+
141
+ const metadataStore = new MetadataStore(createRamStorage());
142
+
143
+ const modelFactory = new ModelFactory().registerModel(ObjectModel);
144
+ const snapshotStore = new SnapshotStore(createStorage('', StorageType.RAM));
145
+
146
+ const partyKey = await keyring.createKeyRecord({ type: KeyType.PARTY });
147
+
148
+ const partyFeedProvider = new PartyFeedProvider(metadataStore, keyring, feedStore, partyKey.publicKey);
149
+
150
+ const otherFeedKey = PublicKey.random();
151
+
152
+ const party = new PartyCore(
153
+ partyKey.publicKey,
154
+ partyFeedProvider,
155
+ modelFactory,
156
+ snapshotStore,
157
+ PublicKey.random()
158
+ );
159
+
160
+ await partyFeedProvider.createOrOpenWritableFeed();
161
+
162
+ const feedOpened = feedStore.feedOpenedEvent.waitForCount(1);
163
+
164
+ await party.open([{ type: KeyType.FEED, publicKey: otherFeedKey }]);
165
+ afterTest(async () => party.close());
166
+
167
+ await feedOpened;
168
+
169
+ expect(partyFeedProvider.getFeeds().some(k => k.key.equals(otherFeedKey))).toEqual(true);
170
+ });
171
+
172
+ test('manually create item', async () => {
173
+ const { party, partyFeedProvider } = await setup();
174
+ await party.open();
175
+
176
+ const feed = await partyFeedProvider.createOrOpenWritableFeed();
177
+
178
+ const itemId = createId();
179
+ await feed.feed.append({
180
+ echo: {
181
+ itemId,
182
+ genesis: {
183
+ itemType: 'dxos:example',
184
+ modelType: ObjectModel.meta.type
185
+ },
186
+ timeframe: new Timeframe()
187
+ }
188
+ });
189
+
190
+ await promiseTimeout(party.database.waitForItem({ id: itemId }), 1000, new Error('timeout'));
191
+ });
192
+
193
+ test('admit a second feed to the party', async () => {
194
+ const { party, keyring, partyKey, feedStore } = await setup();
195
+ await party.open();
196
+
197
+ const feedKey = await keyring.createKeyRecord({ type: KeyType.FEED });
198
+ const fullKey = keyring.getFullKey(feedKey.publicKey);
199
+ const feed2 = await feedStore.openReadWriteFeed(fullKey!.publicKey, fullKey!.secretKey!);
200
+
201
+ await party.processor.writeHaloMessage(createFeedAdmitMessage(
202
+ keyring,
203
+ party.key,
204
+ feed2.key,
205
+ [partyKey]
206
+ ));
207
+
208
+ const itemId = createId();
209
+ await feed2.append({
210
+ echo: {
211
+ itemId,
212
+ genesis: {
213
+ itemType: 'dxos:example',
214
+ modelType: ObjectModel.meta.type
215
+ },
216
+ timeframe: new Timeframe()
217
+ }
218
+ });
219
+
220
+ await promiseTimeout(party.database.waitForItem({ id: itemId }), 1000, new Error('timeout'));
221
+ });
222
+
223
+ test('admit feed and then open it', async () => {
224
+ const { party, keyring, partyKey, feedStore } = await setup();
225
+ await party.open();
226
+
227
+ const feedKey = await keyring.createKeyRecord({ type: KeyType.FEED });
228
+ const fullKey = keyring.getFullKey(feedKey.publicKey);
229
+
230
+ await party.processor.writeHaloMessage(createFeedAdmitMessage(
231
+ keyring,
232
+ party.key,
233
+ feedKey.publicKey,
234
+ [partyKey]
235
+ ));
236
+
237
+ const feed2 = await feedStore.openReadWriteFeed(fullKey!.publicKey, fullKey!.secretKey!);
238
+ const itemId = createId();
239
+ await feed2.append({
240
+ echo: {
241
+ itemId,
242
+ genesis: {
243
+ itemType: 'dxos:example',
244
+ modelType: ObjectModel.meta.type
245
+ },
246
+ timeframe: new Timeframe()
247
+ }
248
+ });
249
+
250
+ await promiseTimeout(party.database.waitForItem({ id: itemId }), 1000, new Error('timeout'));
251
+ });
252
+
253
+ test('self-admitting feed with a hint', async () => {
254
+ const { party, keyring, partyKey, feedStore } = await setup();
255
+ await party.open();
256
+
257
+ const feedKey = await keyring.createKeyRecord({ type: KeyType.FEED });
258
+ const fullKey = keyring.getFullKey(feedKey.publicKey);
259
+ const feed2 = await feedStore.openReadWriteFeed(fullKey!.publicKey, fullKey!.secretKey!);
260
+
261
+ await party.processor.takeHints([{
262
+ type: KeyType.FEED,
263
+ publicKey: feedKey.publicKey
264
+ }]);
265
+
266
+ await feed2.append({
267
+ halo: createFeedAdmitMessage(
268
+ keyring,
269
+ party.key,
270
+ feedKey.publicKey,
271
+ [partyKey]
272
+ )
273
+ });
274
+
275
+ const itemId = createId();
276
+ await feed2.append({
277
+ echo: {
278
+ itemId,
279
+ genesis: {
280
+ itemType: 'dxos:example',
281
+ modelType: ObjectModel.meta.type
282
+ },
283
+ timeframe: new Timeframe()
284
+ }
285
+ });
286
+
287
+ await promiseTimeout(party.database.waitForItem({ id: itemId }), 1000, new Error('timeout'));
288
+ });
289
+
290
+ test('two instances replicating', async () => {
291
+ const peer1 = await setup();
292
+
293
+ const storage = createStorage('', StorageType.RAM);
294
+ const feedStore = new FeedStore(storage, { valueEncoding: codec });
295
+ afterTest(async () => feedStore.close());
296
+
297
+ const metadataStore = new MetadataStore(createRamStorage());
298
+
299
+ const modelFactory = new ModelFactory().registerModel(ObjectModel);
300
+ const snapshotStore = new SnapshotStore(createStorage('', StorageType.RAM));
301
+
302
+ const partyFeedProvider = new PartyFeedProvider(metadataStore, peer1.keyring, feedStore, peer1.party.key);
303
+
304
+ const party2 = new PartyCore(
305
+ peer1.party.key,
306
+ partyFeedProvider,
307
+ modelFactory,
308
+ snapshotStore,
309
+ PublicKey.random()
310
+ );
311
+
312
+ const feed2 = await partyFeedProvider.createOrOpenWritableFeed();
313
+
314
+ await peer1.party.processor.writeHaloMessage(createFeedAdmitMessage(
315
+ peer1.keyring,
316
+ peer1.party.key,
317
+ feed2.key,
318
+ [peer1.partyKey]
319
+ ));
320
+
321
+ await party2.open([{
322
+ publicKey: peer1.feedKey,
323
+ type: KeyType.FEED
324
+ }]);
325
+ afterTest(async () => party2.close());
326
+
327
+ createTestProtocolPair(
328
+ new ReplicatorProtocolPluginFactory(
329
+ peer1.partyFeedProvider,
330
+ peer1.party.processor.getActiveFeedSet()
331
+ ).createPlugins().map(r => r.createExtension()),
332
+ new ReplicatorProtocolPluginFactory(
333
+ partyFeedProvider,
334
+ peer1.party.processor.getActiveFeedSet()
335
+ ).createPlugins().map(r => r.createExtension())
336
+ );
337
+
338
+ const item1 = await peer1.party.database.createItem();
339
+ await promiseTimeout(party2.database.waitForItem({ id: item1.id }), 1000, new Error('timeout'));
340
+ });
118
341
  });
@@ -113,9 +113,14 @@ export class PartyCore {
113
113
 
114
114
  if (!this._partyProcessor) {
115
115
  this._partyProcessor = new PartyProcessor(this._partyKey);
116
- if (keyHints.length > 0) {
117
- await this._partyProcessor.takeHints(keyHints);
118
- }
116
+ }
117
+ // Automatically open new admitted feeds.
118
+ this._subscriptions.push(this._partyProcessor.feedAdded.on(feed => {
119
+ void this._feedProvider.createOrOpenReadOnlyFeed(feed);
120
+ }));
121
+
122
+ if (keyHints.length > 0) {
123
+ await this._partyProcessor.takeHints(keyHints);
119
124
  }
120
125
 
121
126
  //
@@ -301,15 +301,20 @@ export class PartyInternal {
301
301
  assert(this.isOpen, 'Party is not open.');
302
302
  return new ResultSet(
303
303
  this.processor.keyOrInfoAdded.debounce(CONTACT_DEBOUNCE_INTERVAL).discardParameter(),
304
- () => this.processor.memberKeys
305
- .filter(publicKey => !this.processor.partyKey.equals(publicKey))
306
- .map((publicKey: PublicKey): PartyMember => {
307
- const displayName = this.processor.getMemberInfo(publicKey)?.displayName;
308
- return {
309
- publicKey,
310
- displayName
311
- };
312
- })
304
+ () => {
305
+ if (!this.isOpen) {
306
+ return [];
307
+ }
308
+ return this.processor.memberKeys
309
+ .filter(publicKey => !this.processor.partyKey.equals(publicKey))
310
+ .map((publicKey: PublicKey): PartyMember => {
311
+ const displayName = this.processor.getMemberInfo(publicKey)?.displayName;
312
+ return {
313
+ publicKey,
314
+ displayName
315
+ };
316
+ });
317
+ }
313
318
  );
314
319
  }
315
320
  }
@@ -29,7 +29,7 @@ import { createWritableFeedStream, FeedStore } from '@dxos/feed-store';
29
29
  import { ModelFactory } from '@dxos/model-factory';
30
30
  import { NetworkManager } from '@dxos/network-manager';
31
31
  import { ObjectModel } from '@dxos/object-model';
32
- import { createStorage, STORAGE_RAM } from '@dxos/random-access-multi-storage';
32
+ import { createStorage, StorageType } from '@dxos/random-access-multi-storage';
33
33
  import { afterTest } from '@dxos/testutils';
34
34
 
35
35
  import { Item } from '../api';
@@ -58,7 +58,7 @@ const log = debug('dxos:echo:parties:party-manager:test');
58
58
  const setup = async (open = true, createIdentity = true) => {
59
59
  const keyring = new Keyring();
60
60
  const metadataStore = new MetadataStore(createRamStorage());
61
- const feedStore = new FeedStore(createStorage('', STORAGE_RAM), { valueEncoding: codec });
61
+ const feedStore = new FeedStore(createStorage('', StorageType.RAM), { valueEncoding: codec });
62
62
 
63
63
  let seedPhrase;
64
64
  if (createIdentity) {
@@ -73,7 +73,7 @@ const setup = async (open = true, createIdentity = true) => {
73
73
  assert(keyring.keys.length === 1);
74
74
  }
75
75
 
76
- const snapshotStore = new SnapshotStore(createStorage('', STORAGE_RAM));
76
+ const snapshotStore = new SnapshotStore(createStorage('', StorageType.RAM));
77
77
  const modelFactory = new ModelFactory().registerModel(ObjectModel);
78
78
  const networkManager = new NetworkManager();
79
79
  const feedProviderFactory = (partyKey: PublicKey) => new PartyFeedProvider(metadataStore, keyring, feedStore, partyKey);
@@ -179,7 +179,7 @@ describe('Party manager', () => {
179
179
  });
180
180
 
181
181
  test('Create from cold start', async () => {
182
- const storage = createStorage('', STORAGE_RAM);
182
+ const storage = createStorage('', StorageType.RAM);
183
183
  const feedStore = new FeedStore(storage, { valueEncoding: codec });
184
184
 
185
185
  const keyring = new Keyring();
@@ -189,7 +189,7 @@ describe('Party manager', () => {
189
189
  await keyring.createKeyRecord({ type: KeyType.DEVICE });
190
190
 
191
191
  const modelFactory = new ModelFactory().registerModel(ObjectModel);
192
- const snapshotStore = new SnapshotStore(createStorage('', STORAGE_RAM));
192
+ const snapshotStore = new SnapshotStore(createStorage('', StorageType.RAM));
193
193
  const networkManager = new NetworkManager();
194
194
  const feedProviderFactory = (partyKey: PublicKey) => new PartyFeedProvider(metadataStore, keyring, feedStore, partyKey);
195
195
  const partyFactory: PartyFactory = new PartyFactory(() => identityManager.identity, networkManager, modelFactory, snapshotStore, feedProviderFactory);
@@ -36,7 +36,7 @@ describe('party-processor', () => {
36
36
 
37
37
  const message: IHaloStream = {
38
38
  meta: {
39
- feedKey: feedKey.publicKey.asUint8Array(),
39
+ feedKey: feedKey.publicKey,
40
40
  seq: 0
41
41
  // TODO(telackey): Should ownership data go here?
42
42
  },
@@ -67,7 +67,7 @@ describe('party-processor', () => {
67
67
 
68
68
  const genesisMessage: IHaloStream = {
69
69
  meta: {
70
- feedKey: feedKey.publicKey.asUint8Array(),
70
+ feedKey: feedKey.publicKey,
71
71
  seq: 0
72
72
  // TODO(telackey): Should ownership data go here?
73
73
  },
@@ -78,7 +78,7 @@ describe('party-processor', () => {
78
78
  const feedKey2 = await keyring.createKeyRecord({ type: KeyType.FEED });
79
79
  const feedAdmit: IHaloStream = {
80
80
  meta: {
81
- feedKey: feedKey.publicKey.asUint8Array(),
81
+ feedKey: feedKey.publicKey,
82
82
  seq: 0
83
83
  // TODO(telackey): Should ownership data go here?
84
84
  },
@@ -106,7 +106,7 @@ describe('party-processor', () => {
106
106
 
107
107
  const genesisMessage: IHaloStream = {
108
108
  meta: {
109
- feedKey: feedKey.publicKey.asUint8Array(),
109
+ feedKey: feedKey.publicKey,
110
110
  seq: 0
111
111
  // TODO(telackey): Should ownership data go here?
112
112
  },
@@ -115,7 +115,7 @@ describe('party-processor', () => {
115
115
  await partyProcessor.processMessage(genesisMessage);
116
116
  const feedAdmit: IHaloStream = {
117
117
  meta: {
118
- feedKey: feedKey.publicKey.asUint8Array(),
118
+ feedKey: feedKey.publicKey,
119
119
  seq: 0
120
120
  // TODO(telackey): Should ownership data go here?
121
121
  },
@@ -129,7 +129,7 @@ describe('party-processor', () => {
129
129
 
130
130
  const keyAdmit: IHaloStream = {
131
131
  meta: {
132
- feedKey: feedKey.publicKey.asUint8Array(),
132
+ feedKey: feedKey.publicKey,
133
133
  seq: 1
134
134
  },
135
135
  data: createEnvelopeMessage(keyring, partyKey.publicKey,
@@ -141,7 +141,7 @@ describe('party-processor', () => {
141
141
 
142
142
  const feedAdmit2: IHaloStream = {
143
143
  meta: {
144
- feedKey: feedKey.publicKey.asUint8Array(),
144
+ feedKey: feedKey.publicKey,
145
145
  seq: 1
146
146
  // TODO(telackey): Should ownership data go here?
147
147
  },
@@ -170,7 +170,7 @@ describe('party-processor', () => {
170
170
  const partyProcessor = new PartyProcessor(partyKey.publicKey);
171
171
  expect(partyProcessor.partyKey).toBeTruthy();
172
172
 
173
- const meta = (seq: number) => ({ feedKey: feedKey.publicKey.asUint8Array(), seq });
173
+ const meta = (seq: number) => ({ feedKey: feedKey.publicKey, seq });
174
174
 
175
175
  await partyProcessor.processMessage({
176
176
  meta: meta(0),
@@ -33,7 +33,7 @@ export class PartyProcessor {
33
33
 
34
34
  private _outboundHaloStream: FeedWriter<HaloMessage> | undefined;
35
35
 
36
- protected readonly _feedAdded = new Event<FeedKey>()
36
+ readonly feedAdded = new Event<FeedKey>()
37
37
 
38
38
  public readonly keyOrInfoAdded = new Event<PublicKey>();
39
39
 
@@ -50,7 +50,7 @@ export class PartyProcessor {
50
50
  // TODO(marik-d): Use `Event.wrap` here.
51
51
  this._state.on(PartyEventType.ADMIT_FEED, (keyRecord: any) => {
52
52
  log(`Feed key admitted ${keyRecord.publicKey.toHex()}`);
53
- this._feedAdded.emit(keyRecord.publicKey);
53
+ this.feedAdded.emit(keyRecord.publicKey);
54
54
  });
55
55
  this._state.on(PartyEventType.ADMIT_KEY, (keyRecord: KeyRecord) => this.keyOrInfoAdded.emit(keyRecord.publicKey));
56
56
  this._state.on(IdentityEventType.UPDATE_IDENTITY, (publicKey: PublicKey) => this.keyOrInfoAdded.emit(publicKey));
@@ -112,7 +112,7 @@ export class PartyProcessor {
112
112
  getActiveFeedSet (): FeedSetProvider {
113
113
  return {
114
114
  get: () => this.feedKeys,
115
- added: this._feedAdded
115
+ added: this.feedAdded
116
116
  };
117
117
  }
118
118
 
@@ -144,7 +144,7 @@ export class PartyProtocolFactory {
144
144
  /**
145
145
  * Creates the protocol plugin for feed replication.
146
146
  */
147
- class ReplicatorProtocolPluginFactory {
147
+ export class ReplicatorProtocolPluginFactory {
148
148
  constructor (
149
149
  private readonly _feedProvider: PartyFeedProvider,
150
150
  private readonly _activeFeeds: FeedSetProvider