@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,10 @@
5
5
  import assert from 'assert';
6
6
 
7
7
  import { synchronized } from '@dxos/async';
8
- import { KeyHint, KeyType } from '@dxos/credentials';
8
+ import { KeyHint, KeyType, Message as HaloMessage } from '@dxos/credentials';
9
9
  import { PublicKey } from '@dxos/crypto';
10
10
  import { timed } from '@dxos/debug';
11
- import { createFeedWriter, DatabaseSnapshot, PartyKey, PartySnapshot, Timeframe } from '@dxos/echo-protocol';
11
+ import { createFeedWriter, DatabaseSnapshot, PartyKey, PartySnapshot, Timeframe, WriteReceipt } from '@dxos/echo-protocol';
12
12
  import { ModelFactory } from '@dxos/model-factory';
13
13
  import { SubscriptionGroup } from '@dxos/util';
14
14
 
@@ -202,6 +202,11 @@ export class PartyCore {
202
202
  return this;
203
203
  }
204
204
 
205
+ writeCredentialsMessage (message: HaloMessage): Promise<WriteReceipt> {
206
+ assert(this._partyProcessor, 'Party not open');
207
+ return this._partyProcessor?.writeHaloMessage(message);
208
+ }
209
+
205
210
  /**
206
211
  * Create a snapshot of the current state.
207
212
  */
@@ -12,7 +12,8 @@ import {
12
12
  PartyState,
13
13
  Message as HaloMessage,
14
14
  IdentityEventType,
15
- PartyEventType
15
+ PartyEventType,
16
+ SignedMessage
16
17
  } from '@dxos/credentials';
17
18
  import { PublicKey } from '@dxos/crypto';
18
19
  import { FeedKey, FeedWriter, IHaloStream, PartyKey, HaloStateSnapshot, WriteReceipt } from '@dxos/echo-protocol';
@@ -20,10 +21,33 @@ import { jsonReplacer } from '@dxos/util';
20
21
 
21
22
  const log = debug('dxos:echo-db:party-processor');
22
23
 
24
+ export interface CredentialWriter {
25
+ writeHaloMessage (message: HaloMessage): Promise<WriteReceipt>
26
+ }
27
+
28
+ export interface CredentialProcessor {
29
+ processMessage (message: IHaloStream): Promise<void>
30
+ }
31
+
32
+ export interface PartyStateProvider {
33
+ partyKey: PublicKey
34
+
35
+ /**
36
+ * Whether PartyGenesis was already processed.
37
+ */
38
+ genesisRequired: boolean
39
+ memberKeys: PublicKey[]
40
+ feedKeys: PublicKey[]
41
+ getFeedOwningMember (feedKey: FeedKey): PublicKey | undefined
42
+ isFeedAdmitted (feedKey: FeedKey): boolean
43
+
44
+ getOfflineInvitation (invitationID: Buffer): SignedMessage | undefined
45
+ }
46
+
23
47
  /**
24
48
  * TODO(burdon): Wrapper/Bridge between HALO APIs.
25
49
  */
26
- export class PartyProcessor {
50
+ export class PartyProcessor implements CredentialWriter, CredentialProcessor, PartyStateProvider {
27
51
  private readonly _state: PartyState;
28
52
 
29
53
  private _outboundHaloStream: FeedWriter<HaloMessage> | undefined;
@@ -25,7 +25,7 @@ const log = debug('dxos:echo:pipeline:test');
25
25
  describe('pipeline', () => {
26
26
  test('streams', async () => {
27
27
  const storage = createStorage('', StorageType.RAM);
28
- const feedStore = new FeedStore(storage, { valueEncoding: codec });
28
+ const feedStore = new FeedStore(storage.directory('feed'), { valueEncoding: codec });
29
29
  const feedKeys: Uint8Array[] = [];
30
30
  const feedSelector: FeedSelector = descriptor => !!feedKeys.find(key => descriptor.key.equals(key));
31
31
  const feedReadStream = new FeedStoreIterator(feedSelector, () => 0, new Timeframe());
@@ -87,7 +87,7 @@ describe('pipeline', () => {
87
87
 
88
88
  test('writing', async () => {
89
89
  const storage = createStorage('', StorageType.RAM);
90
- const feedStore = new FeedStore(storage, { valueEncoding: codec });
90
+ const feedStore = new FeedStore(storage.directory('feed'), { valueEncoding: codec });
91
91
  const feedReadStream = new FeedStoreIterator(() => true, () => 0, new Timeframe());
92
92
 
93
93
  const { publicKey, secretKey } = createKeyPair();
@@ -17,7 +17,7 @@ import { createReadable } from '@dxos/feed-store';
17
17
  import { jsonReplacer } from '@dxos/util';
18
18
 
19
19
  import { TimeframeClock } from '../database';
20
- import { PartyProcessor } from './party-processor';
20
+ import { CredentialProcessor, PartyStateProvider } from './party-processor';
21
21
 
22
22
  interface Options {
23
23
  readLogger?: (msg: any) => void
@@ -55,17 +55,13 @@ export class Pipeline {
55
55
  * @param _options
56
56
  */
57
57
  constructor (
58
- private readonly _partyProcessor: PartyProcessor,
58
+ private readonly _partyProcessor: CredentialProcessor & PartyStateProvider,
59
59
  private readonly _feedStorIterator: FeedStoreIterator,
60
60
  private readonly _timeframeClock: TimeframeClock,
61
61
  private readonly _feedWriter?: FeedWriter<FeedMessage>,
62
62
  private readonly _options: Options = {}
63
63
  ) {}
64
64
 
65
- get partyKey () {
66
- return this._partyProcessor.partyKey;
67
- }
68
-
69
65
  get isOpen () {
70
66
  return this._inboundEchoStream !== undefined;
71
67
  }
@@ -9,6 +9,4 @@ import { Replicator } from '@dxos/protocol-plugin-replicator';
9
9
  /**
10
10
  * Creates authenticator network-protocol plugin that guards access to the replicator.
11
11
  */
12
- export function createAuthPlugin (authenticator: Authenticator, peerId: PublicKey) {
13
- return new AuthPlugin(peerId.asBuffer(), authenticator, [Replicator.extension]);
14
- }
12
+ export const createAuthPlugin = (authenticator: Authenticator, peerId: PublicKey) => new AuthPlugin(peerId.asBuffer(), authenticator, [Replicator.extension]);
@@ -12,19 +12,17 @@ import { CredentialsSigner } from './credentials-signer';
12
12
 
13
13
  const log = debug('dxos:echo-db:authenticator');
14
14
 
15
- export function createAuthenticator (partyProcessor: PartyProcessor, credentialsSigner: CredentialsSigner): Authenticator {
16
- return new PartyAuthenticator(partyProcessor.state, async auth => {
17
- if (auth.feedAdmit && auth.feedKey && !partyProcessor.isFeedAdmitted(auth.feedKey)) {
18
- log(`Admitting feed of authenticated member: ${auth.feedKey}`);
19
- await partyProcessor.writeHaloMessage(createEnvelopeMessage(
20
- credentialsSigner.signer,
21
- partyProcessor.partyKey,
22
- auth.feedAdmit,
23
- [credentialsSigner.getDeviceSigningKeys()]
24
- ));
25
- }
26
- });
27
- }
15
+ export const createAuthenticator = (partyProcessor: PartyProcessor, credentialsSigner: CredentialsSigner): Authenticator => new PartyAuthenticator(partyProcessor.state, async auth => {
16
+ if (auth.feedAdmit && auth.feedKey && !partyProcessor.isFeedAdmitted(auth.feedKey)) {
17
+ log(`Admitting feed of authenticated member: ${auth.feedKey}`);
18
+ await partyProcessor.writeHaloMessage(createEnvelopeMessage(
19
+ credentialsSigner.signer,
20
+ partyProcessor.partyKey,
21
+ auth.feedAdmit,
22
+ [credentialsSigner.getDeviceSigningKeys()]
23
+ ));
24
+ }
25
+ });
28
26
 
29
27
  export interface CredentialsProvider {
30
28
  /**
@@ -33,24 +31,22 @@ export interface CredentialsProvider {
33
31
  get (): Buffer
34
32
  }
35
33
 
36
- export function createCredentialsProvider (credentialsSigner: CredentialsSigner, partyKey: PartyKey, feedKey: FeedKey): CredentialsProvider {
37
- return {
38
- get: () => {
39
- const authMessage = createAuthMessage(
34
+ export const createCredentialsProvider = (credentialsSigner: CredentialsSigner, partyKey: PartyKey, feedKey: FeedKey): CredentialsProvider => ({
35
+ get: () => {
36
+ const authMessage = createAuthMessage(
37
+ credentialsSigner.signer,
38
+ partyKey,
39
+ credentialsSigner.getIdentityKey(),
40
+ credentialsSigner.getDeviceSigningKeys(),
41
+ feedKey,
42
+ undefined,
43
+ createFeedAdmitMessage(
40
44
  credentialsSigner.signer,
41
45
  partyKey,
42
- credentialsSigner.getIdentityKey(),
43
- credentialsSigner.getDeviceSigningKeys(),
44
46
  feedKey,
45
- undefined,
46
- createFeedAdmitMessage(
47
- credentialsSigner.signer,
48
- partyKey,
49
- feedKey,
50
- [feedKey, credentialsSigner.getDeviceSigningKeys()]
51
- )
52
- );
53
- return Buffer.from(codec.encode(authMessage));
54
- }
55
- };
56
- }
47
+ [feedKey, credentialsSigner.getDeviceSigningKeys()]
48
+ )
49
+ );
50
+ return Buffer.from(codec.encode(authMessage));
51
+ }
52
+ });
@@ -12,9 +12,7 @@ import { HaloRecoveryInitiator, InvitationFactory } from '../invitations';
12
12
  * Plugin is intended to be used in HALO party swarm.
13
13
  *
14
14
  */
15
- export function createHaloRecoveryPlugin (identityKey: PublicKey, invitationFactory: InvitationFactory, peerId: PublicKey) {
16
- return new GreetingCommandPlugin(
17
- peerId.asBuffer(),
18
- HaloRecoveryInitiator.createHaloInvitationClaimHandler(identityKey, invitationFactory)
19
- );
20
- }
15
+ export const createHaloRecoveryPlugin = (identityKey: PublicKey, invitationFactory: InvitationFactory, peerId: PublicKey) => new GreetingCommandPlugin(
16
+ peerId.asBuffer(),
17
+ HaloRecoveryInitiator.createHaloInvitationClaimHandler(identityKey, invitationFactory)
18
+ );
@@ -25,7 +25,7 @@ export interface IdentityCredentials {
25
25
 
26
26
  export type IdentityCredentialsProvider = () => IdentityCredentials | undefined
27
27
 
28
- export async function createTestIdentityCredentials (keyring: Keyring): Promise<IdentityCredentials> {
28
+ export const createTestIdentityCredentials = async (keyring: Keyring): Promise<IdentityCredentials> => {
29
29
  const identityKey = await keyring.createKeyRecord({ type: KeyType.IDENTITY });
30
30
  const deviceKey = await keyring.createKeyRecord({ type: KeyType.DEVICE });
31
31
  const feedKey = await keyring.createKeyRecord({ type: KeyType.FEED });
@@ -53,9 +53,9 @@ export async function createTestIdentityCredentials (keyring: Keyring): Promise<
53
53
  preferences: undefined,
54
54
  contacts: undefined
55
55
  };
56
- }
56
+ };
57
57
 
58
- export async function deriveTestDeviceCredentials (identity: IdentityCredentials): Promise<IdentityCredentials> {
58
+ export const deriveTestDeviceCredentials = async (identity: IdentityCredentials): Promise<IdentityCredentials> => {
59
59
  const deviceKey = await identity.keyring.createKeyRecord({ type: KeyType.DEVICE });
60
60
  const keyAdmit = createKeyAdmitMessage(identity.keyring, identity.identityKey.publicKey, deviceKey, [identity.identityKey]);
61
61
 
@@ -75,4 +75,4 @@ export async function deriveTestDeviceCredentials (identity: IdentityCredentials
75
75
  deviceKeyChain
76
76
  )
77
77
  };
78
- }
78
+ };
@@ -11,9 +11,7 @@ import { InvitationFactory, OfflineInvitationClaimer } from '../invitations';
11
11
  * Creates network protocol plugin that allows peers to claim offline invitations.
12
12
  * Plugin is intended to be used in data-party swarms.
13
13
  */
14
- export function createOfflineInvitationPlugin (invitationFactory: InvitationFactory, peerId: PublicKey) {
15
- return new GreetingCommandPlugin(
16
- peerId.asBuffer(),
17
- OfflineInvitationClaimer.createOfflineInvitationClaimHandler(invitationFactory)
18
- );
19
- }
14
+ export const createOfflineInvitationPlugin = (invitationFactory: InvitationFactory, peerId: PublicKey) => new GreetingCommandPlugin(
15
+ peerId.asBuffer(),
16
+ OfflineInvitationClaimer.createOfflineInvitationClaimHandler(invitationFactory)
17
+ );
@@ -4,17 +4,13 @@
4
4
 
5
5
  import debug from 'debug';
6
6
 
7
- import { synchronized } from '@dxos/async';
8
7
  import { discoveryKey, keyToString, PublicKey } from '@dxos/crypto';
9
- import { FeedKey, PartyKey } from '@dxos/echo-protocol';
10
- import type { HypercoreFeed } from '@dxos/feed-store';
8
+ import { PartyKey } from '@dxos/echo-protocol';
11
9
  import { Protocol } from '@dxos/mesh-protocol';
12
10
  import { MMSTTopology, NetworkManager, Plugin } from '@dxos/network-manager';
13
11
  import { PresencePlugin } from '@dxos/protocol-plugin-presence';
14
- import { Replicator } from '@dxos/protocol-plugin-replicator';
15
12
 
16
13
  import { CredentialsProvider } from '.';
17
- import { PartyFeedProvider } from '../pipeline/party-feed-provider';
18
14
 
19
15
  const log = debug('dxos:echo-db:party-protocol-factory');
20
16
 
@@ -23,21 +19,15 @@ const log = debug('dxos:echo-db:party-protocol-factory');
23
19
  */
24
20
  export class PartyProtocolFactory {
25
21
  private readonly _presencePlugin = new PresencePlugin(this._peerId.asBuffer());
26
- private readonly _replicatorProtocolPluginFactory: ReplicatorProtocolPluginFactory;
27
22
 
28
23
  private _started = false;
29
24
 
30
25
  constructor (
31
26
  private readonly _partyKey: PartyKey,
32
27
  private readonly _networkManager: NetworkManager,
33
- private readonly _feedProvider: PartyFeedProvider,
34
28
  private readonly _peerId: PublicKey,
35
29
  private readonly _credentials: CredentialsProvider
36
- ) {
37
- // Replication.
38
- this._replicatorProtocolPluginFactory =
39
- new ReplicatorProtocolPluginFactory(this._feedProvider);
40
- }
30
+ ) {}
41
31
 
42
32
  async start (plugins: Plugin[]) {
43
33
  if (this._started) {
@@ -73,9 +63,8 @@ export class PartyProtocolFactory {
73
63
  await this._networkManager.leaveProtocolSwarm(this._partyKey);
74
64
  }
75
65
 
76
- private _createProtocol (channel: any, opts: {initiator: boolean}, extraPlugins: Plugin[]) {
66
+ private _createProtocol (channel: any, opts: { initiator: boolean }, extraPlugins: Plugin[]) {
77
67
  const plugins: Plugin[] = [
78
- ...this._replicatorProtocolPluginFactory.createPlugins(),
79
68
  ...extraPlugins,
80
69
  this._presencePlugin
81
70
  ];
@@ -118,45 +107,3 @@ export class PartyProtocolFactory {
118
107
  return protocol;
119
108
  }
120
109
  }
121
-
122
- /**
123
- * Creates the protocol plugin for feed replication.
124
- */
125
- export class ReplicatorProtocolPluginFactory {
126
- constructor (
127
- private readonly _feedProvider: PartyFeedProvider
128
- ) {}
129
-
130
- createPlugins () {
131
- return [
132
- new Replicator({
133
- load: async () => {
134
- const feeds = this._feedProvider.getFeeds();
135
- log(`Loading feeds: ${feeds.map(feed => keyToString(feed.key))}`);
136
- return feeds.map((feed) => ({ discoveryKey: feed.feed.discoveryKey }));
137
- },
138
-
139
- subscribe: (addFeedToReplicatedSet: (feed: any) => void) => {
140
- return this._feedProvider.feedOpened.on(async (feed) => {
141
- log(`Adding feed: ${feed.key.toHex()}`);
142
- addFeedToReplicatedSet({ discoveryKey: feed.feed.discoveryKey });
143
- });
144
- },
145
-
146
- replicate: async (remoteFeeds, info) => {
147
- // We can ignore remoteFeeds entirely, since the set of feeds we want to replicate is dictated by the Party.
148
- // TODO(telackey): Why are we opening feeds? Necessary or belt/braces thinking, or because open party does it?
149
- const feeds = this._feedProvider.getFeeds();
150
- log(`Replicating: peerId=${info.session}; feeds=${feeds.map(feed => feed.key.toHex())}`);
151
- return feeds.map(feed => feed.feed);
152
- }
153
- })
154
- ];
155
- }
156
-
157
- @synchronized
158
- private async _openFeed (key: FeedKey): Promise<HypercoreFeed> {
159
- const descriptor = await this._feedProvider.createOrOpenReadOnlyFeed(key);
160
- return descriptor.feed;
161
- }
162
- }
@@ -0,0 +1,37 @@
1
+ //
2
+ // Copyright 2022 DXOS.org
3
+ //
4
+
5
+ import debug from 'debug';
6
+
7
+ import { keyToString } from '@dxos/crypto';
8
+ import { Replicator } from '@dxos/protocol-plugin-replicator';
9
+
10
+ import { PartyFeedProvider } from '../pipeline';
11
+
12
+ const log = debug('dxos:echo-db:protocol:replicator');
13
+
14
+ /**
15
+ * Creates the protocol plugin for feed replication.
16
+ */
17
+ export const createReplicatorPlugin = (feedProvider: PartyFeedProvider) =>
18
+ new Replicator({
19
+ load: async () => {
20
+ const feeds = feedProvider.getFeeds();
21
+ log(`Loading feeds: ${feeds.map(feed => keyToString(feed.key))}`);
22
+ return feeds.map((feed) => ({ discoveryKey: feed.feed.discoveryKey }));
23
+ },
24
+
25
+ subscribe: (addFeedToReplicatedSet: (feed: any) => void) => feedProvider.feedOpened.on(async (feed) => {
26
+ log(`Adding feed: ${feed.key.toHex()}`);
27
+ addFeedToReplicatedSet({ discoveryKey: feed.feed.discoveryKey });
28
+ }),
29
+
30
+ replicate: async (remoteFeeds, info) => {
31
+ // We can ignore remoteFeeds entirely, since the set of feeds we want to replicate is dictated by the Party.
32
+ // TODO(telackey): Why are we opening feeds? Necessary or belt/braces thinking, or because open party does it?
33
+ const feeds = feedProvider.getFeeds();
34
+ log(`Replicating: peerId=${info.session}; feeds=${feeds.map(feed => feed.key.toHex())}`);
35
+ return feeds.map(feed => feed.feed);
36
+ }
37
+ });
@@ -10,20 +10,16 @@ import { SnapshotStore } from './snapshot-store';
10
10
 
11
11
  const log = debug('dxos:snapshot-generator');
12
12
 
13
- export function createAutomaticSnapshots (
14
- party: PartyCore, clock: TimeframeClock, store: SnapshotStore, interval: number
15
- ) {
16
- return clock.update.on(async timeframe => {
17
- const totalMessages = timeframe.totalMessages();
18
- if (totalMessages > 0 && totalMessages % interval === 0) {
19
- log(`Saving snapshot of ${party.key.humanize()}...`);
20
- try {
21
- const snapshot = party.createSnapshot();
22
- await store.save(snapshot);
23
- } catch (err: any) {
24
- console.error('Failed to save snapshot');
25
- console.error(err);
26
- }
13
+ export const createAutomaticSnapshots = (party: PartyCore, clock: TimeframeClock, store: SnapshotStore, interval: number) => clock.update.on(async timeframe => {
14
+ const totalMessages = timeframe.totalMessages();
15
+ if (totalMessages > 0 && totalMessages % interval === 0) {
16
+ log(`Saving snapshot of ${party.key.humanize()}...`);
17
+ try {
18
+ const snapshot = party.createSnapshot();
19
+ await store.save(snapshot);
20
+ } catch (err: any) {
21
+ console.error('Failed to save snapshot');
22
+ console.error(err);
27
23
  }
28
- });
29
- }
24
+ }
25
+ });
@@ -7,15 +7,15 @@ import { it as test } from 'mocha';
7
7
 
8
8
  import { createId, createKeyPair, PublicKey } from '@dxos/crypto';
9
9
  import { PartySnapshot } from '@dxos/echo-protocol';
10
+ import { createStorage, StorageType } from '@dxos/random-access-multi-storage';
10
11
 
11
- import { createRamStorage } from '../util';
12
12
  import { SnapshotStore } from './snapshot-store';
13
13
 
14
14
  const createPublicKey = () => PublicKey.from(createKeyPair().publicKey);
15
15
 
16
16
  describe('SnapshotStore', () => {
17
17
  test('in-memory', async () => {
18
- const store = new SnapshotStore(createRamStorage());
18
+ const store = new SnapshotStore(createStorage('', StorageType.RAM).directory('snapshots'));
19
19
 
20
20
  const key1 = createPublicKey();
21
21
  const key2 = createPublicKey();
@@ -7,10 +7,9 @@ import debug from 'debug';
7
7
 
8
8
  import { keyToString } from '@dxos/crypto';
9
9
  import { schema, PartyKey, PartySnapshot } from '@dxos/echo-protocol';
10
- import { IStorage } from '@dxos/random-access-multi-storage';
10
+ import { Directory } from '@dxos/random-access-multi-storage';
11
11
 
12
12
  const log = debug('dxos:snapshot-store');
13
-
14
13
  /**
15
14
  * Stores party snapshots. Takes any `random-access-storage` compatible backend.
16
15
  *
@@ -18,11 +17,11 @@ const log = debug('dxos:snapshot-store');
18
17
  */
19
18
  export class SnapshotStore {
20
19
  constructor (
21
- private readonly _storage: IStorage
20
+ private readonly _directory: Directory
22
21
  ) {}
23
22
 
24
23
  async load (partyKey: PartyKey): Promise<PartySnapshot | undefined> {
25
- const file = this._storage.createOrOpen(partyKey.toHex());
24
+ const file = this._directory.createOrOpen(partyKey.toHex());
26
25
 
27
26
  try {
28
27
  const { size } = await file.stat();
@@ -45,7 +44,7 @@ export class SnapshotStore {
45
44
 
46
45
  async save (snapshot: PartySnapshot) {
47
46
  assert(snapshot.partyKey);
48
- const file = this._storage.createOrOpen(keyToString(snapshot.partyKey), { truncate: true, size: 0 });
47
+ const file = this._directory.createOrOpen(keyToString(snapshot.partyKey), { truncate: true, size: 0 });
49
48
 
50
49
  try {
51
50
  const data = schema.getCodecForType('dxos.echo.snapshot.PartySnapshot').encode(snapshot);
@@ -60,6 +59,6 @@ export class SnapshotStore {
60
59
  */
61
60
  async clear () {
62
61
  log('Clearing all snapshots..');
63
- await this._storage.destroy();
62
+ await this._directory.destroy();
64
63
  }
65
64
  }
@@ -0,0 +1,30 @@
1
+ //
2
+ // Copyright 2022 DXOS.org
3
+ //
4
+
5
+ import { ObjectModel } from '@dxos/object-model';
6
+
7
+ import { ECHO } from '../echo';
8
+
9
+ const ITEMS = 100;
10
+ const MUTATIONS = 1000;
11
+
12
+ it.skip('Database benchmark', async () => {
13
+ const echo = new ECHO({ snapshots: false });
14
+ await echo.open();
15
+ await echo.halo.createProfile();
16
+ const party = await echo.createParty();
17
+
18
+ const start = Date.now();
19
+ for (let i = 0; i < ITEMS; i++) {
20
+ const item = await party.database.createItem({ model: ObjectModel, type: 'test:item' });
21
+
22
+ for (let j = 0; j < MUTATIONS; j++) {
23
+ await item.model.set(`key${j % 100}`, `value-${j}`);
24
+ }
25
+
26
+ console.log(`${i * MUTATIONS}/${ITEMS * MUTATIONS} ${((Date.now() - start) / ((i + 1) * MUTATIONS / 1000)).toFixed(1)} µs/mut ${((i + 1) * MUTATIONS / (Date.now() - start) * 1000).toFixed(1)} mut/s`);
27
+ }
28
+
29
+ await echo.close();
30
+ });
@@ -22,10 +22,10 @@ export type TestPeer = Awaited<ReturnType<typeof createTestInstance>>;
22
22
 
23
23
  export type WithTestMeta<T> = T & { testMeta: TestPeer }
24
24
 
25
- function addTestMeta<T> (obj: T, meta: TestPeer): WithTestMeta<T> {
25
+ const addTestMeta = <T>(obj: T, meta: TestPeer): WithTestMeta<T> => {
26
26
  (obj as any).testMeta = meta;
27
27
  return obj as any;
28
- }
28
+ };
29
29
 
30
30
  /**
31
31
  * Creates a number of test ECHO instances and a party that's shared between all of them.
@@ -5,12 +5,11 @@
5
5
  import debug from 'debug';
6
6
 
7
7
  import { NetworkManagerOptions } from '@dxos/network-manager';
8
- import { IStorage } from '@dxos/random-access-multi-storage';
8
+ import { Storage, createStorage, StorageType } from '@dxos/random-access-multi-storage';
9
9
  import { jsonReplacer } from '@dxos/util';
10
10
 
11
11
  import { ECHO } from '../echo';
12
12
  import { DataParty } from '../parties';
13
- import { createRamStorage } from '../util';
14
13
 
15
14
  export const log = debug('dxos:echo-db:testing');
16
15
 
@@ -21,13 +20,12 @@ export const messageLogger = (tag: string) => (message: any) => {
21
20
  export interface TestOptions {
22
21
  verboseLogging?: boolean
23
22
  initialize?: boolean
24
- storage?: any
23
+ storage?: Storage
25
24
  keyStorage?: any
26
25
  networkManagerOptions?: NetworkManagerOptions
27
26
  // TODO(burdon): Group properties by hierarchical object.
28
27
  snapshots?: boolean
29
28
  snapshotInterval?: number
30
- snapshotStorage?: IStorage
31
29
  }
32
30
 
33
31
  /**
@@ -36,17 +34,15 @@ export interface TestOptions {
36
34
  export const createTestInstance = async ({
37
35
  verboseLogging = false,
38
36
  initialize = false,
39
- storage = createRamStorage(),
37
+ storage = createStorage('', StorageType.RAM),
40
38
  keyStorage = undefined,
41
39
  networkManagerOptions,
42
- snapshotStorage = createRamStorage(),
43
40
  snapshots = true,
44
41
  snapshotInterval
45
42
  }: TestOptions = {}) => {
46
43
  const echo = new ECHO({
47
- feedStorage: storage,
44
+ storage,
48
45
  keyStorage,
49
- snapshotStorage,
50
46
  snapshotInterval,
51
47
  snapshots,
52
48
  networkManagerOptions,
@@ -1,2 +0,0 @@
1
- export * from './persistant-ram-storage';
2
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/util/index.ts"],"names":[],"mappings":"AAIA,cAAc,0BAA0B,CAAC"}
@@ -1,17 +0,0 @@
1
- "use strict";
2
- //
3
- // Copyright 2020 DXOS.org
4
- //
5
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
- if (k2 === undefined) k2 = k;
7
- Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
8
- }) : (function(o, m, k, k2) {
9
- if (k2 === undefined) k2 = k;
10
- o[k2] = m[k];
11
- }));
12
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
13
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
14
- };
15
- Object.defineProperty(exports, "__esModule", { value: true });
16
- __exportStar(require("./persistant-ram-storage"), exports);
17
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/util/index.ts"],"names":[],"mappings":";AAAA,EAAE;AACF,0BAA0B;AAC1B,EAAE;;;;;;;;;;;;AAEF,2DAAyC"}
@@ -1,6 +0,0 @@
1
- import { IStorage } from '@dxos/random-access-multi-storage';
2
- /**
3
- * A wrapper around RAM storage that preserves file data when closing and re-opening files.
4
- */
5
- export declare function createRamStorage(): IStorage;
6
- //# sourceMappingURL=persistant-ram-storage.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"persistant-ram-storage.d.ts","sourceRoot":"","sources":["../../../src/util/persistant-ram-storage.ts"],"names":[],"mappings":"AAIA,OAAO,EAAoC,QAAQ,EAAE,MAAM,mCAAmC,CAAC;AAE/F;;GAEG;AAEH,wBAAgB,gBAAgB,IAAK,QAAQ,CAsB5C"}
@@ -1,32 +0,0 @@
1
- "use strict";
2
- //
3
- // Copyright 2020 DXOS.org
4
- //
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.createRamStorage = void 0;
7
- const random_access_multi_storage_1 = require("@dxos/random-access-multi-storage");
8
- /**
9
- * A wrapper around RAM storage that preserves file data when closing and re-opening files.
10
- */
11
- // TODO(burdon): Factor out?
12
- function createRamStorage() {
13
- const root = 'snapshots';
14
- const storage = (0, random_access_multi_storage_1.createStorage)(root, random_access_multi_storage_1.StorageType.RAM);
15
- const files = new Map();
16
- const fn = {};
17
- fn.createOrOpen = (name) => {
18
- if (files.has(name)) {
19
- return files.get(name);
20
- }
21
- const file = storage.createOrOpen(name);
22
- file.close = (cb) => cb === null || cb === void 0 ? void 0 : cb(null); // Fix.
23
- files.set(name, file);
24
- return file;
25
- };
26
- fn.root = root;
27
- fn.type = storage.type;
28
- fn.destroy = storage.destroy.bind(storage);
29
- return fn;
30
- }
31
- exports.createRamStorage = createRamStorage;
32
- //# sourceMappingURL=persistant-ram-storage.js.map