@dxos/echo-db 2.33.9-dev.7d11f506 → 2.33.9-dev.9bbef4e2

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 (175) hide show
  1. package/dist/src/api/index.d.ts +1 -0
  2. package/dist/src/api/index.d.ts.map +1 -1
  3. package/dist/src/api/index.js +1 -0
  4. package/dist/src/api/index.js.map +1 -1
  5. package/dist/src/api/result-set.js +4 -4
  6. package/dist/src/api/result-set.js.map +1 -1
  7. package/dist/src/api/subscription.d.ts +5 -0
  8. package/dist/src/api/subscription.d.ts.map +1 -0
  9. package/dist/src/api/subscription.js +25 -0
  10. package/dist/src/api/subscription.js.map +1 -0
  11. package/dist/src/echo-api.test.d.ts +2 -0
  12. package/dist/src/echo-api.test.d.ts.map +1 -0
  13. package/dist/src/echo-api.test.js +117 -0
  14. package/dist/src/echo-api.test.js.map +1 -0
  15. package/dist/src/echo.d.ts +3 -4
  16. package/dist/src/echo.d.ts.map +1 -1
  17. package/dist/src/echo.js +6 -8
  18. package/dist/src/echo.js.map +1 -1
  19. package/dist/src/echo.test.js +3 -3
  20. package/dist/src/echo.test.js.map +1 -1
  21. package/dist/src/halo/halo-factory.js +8 -8
  22. package/dist/src/halo/halo-factory.js.map +1 -1
  23. package/dist/src/halo/halo-party.d.ts +2 -2
  24. package/dist/src/halo/halo-party.d.ts.map +1 -1
  25. package/dist/src/halo/halo-party.js +3 -3
  26. package/dist/src/halo/halo-party.js.map +1 -1
  27. package/dist/src/halo/halo.js +9 -9
  28. package/dist/src/halo/halo.js.map +1 -1
  29. package/dist/src/halo/halo.test.js.map +1 -1
  30. package/dist/src/halo/identity-manager.d.ts.map +1 -1
  31. package/dist/src/halo/identity-manager.js +7 -10
  32. package/dist/src/halo/identity-manager.js.map +1 -1
  33. package/dist/src/halo/identity.d.ts +1 -1
  34. package/dist/src/halo/identity.d.ts.map +1 -1
  35. package/dist/src/halo/identity.js +4 -2
  36. package/dist/src/halo/identity.js.map +1 -1
  37. package/dist/src/halo/preferences.d.ts.map +1 -1
  38. package/dist/src/halo/preferences.js +6 -6
  39. package/dist/src/halo/preferences.js.map +1 -1
  40. package/dist/src/invitations/greeting-initiator.js +6 -6
  41. package/dist/src/invitations/greeting-initiator.js.map +1 -1
  42. package/dist/src/invitations/greeting-responder.js +5 -5
  43. package/dist/src/invitations/greeting-responder.js.map +1 -1
  44. package/dist/src/invitations/halo-recovery-initiator.js +6 -6
  45. package/dist/src/invitations/halo-recovery-initiator.js.map +1 -1
  46. package/dist/src/invitations/invitation-descriptor.js +9 -9
  47. package/dist/src/invitations/invitation-descriptor.js.map +1 -1
  48. package/dist/src/invitations/invitation-factory.js +3 -3
  49. package/dist/src/invitations/invitation-factory.js.map +1 -1
  50. package/dist/src/invitations/offline-invitation-claimer.js +7 -7
  51. package/dist/src/invitations/offline-invitation-claimer.js.map +1 -1
  52. package/dist/src/packlets/database/data-mirror.js +8 -8
  53. package/dist/src/packlets/database/data-mirror.js.map +1 -1
  54. package/dist/src/packlets/database/data-service-host.js +3 -3
  55. package/dist/src/packlets/database/data-service-host.js.map +1 -1
  56. package/dist/src/packlets/database/data-service-router.js +5 -5
  57. package/dist/src/packlets/database/data-service-router.js.map +1 -1
  58. package/dist/src/packlets/database/database-backend.js +3 -3
  59. package/dist/src/packlets/database/database-backend.js.map +1 -1
  60. package/dist/src/packlets/database/database.js +2 -2
  61. package/dist/src/packlets/database/database.js.map +1 -1
  62. package/dist/src/packlets/database/item-demuxer.js +14 -14
  63. package/dist/src/packlets/database/item-demuxer.js.map +1 -1
  64. package/dist/src/packlets/database/item-manager.d.ts.map +1 -1
  65. package/dist/src/packlets/database/item-manager.js +18 -18
  66. package/dist/src/packlets/database/item-manager.js.map +1 -1
  67. package/dist/src/packlets/database/link.js +3 -3
  68. package/dist/src/packlets/database/link.js.map +1 -1
  69. package/dist/src/packlets/database/selection/result.js +2 -2
  70. package/dist/src/packlets/database/selection/result.js.map +1 -1
  71. package/dist/src/parties/data-party.d.ts.map +1 -1
  72. package/dist/src/parties/data-party.js +11 -11
  73. package/dist/src/parties/data-party.js.map +1 -1
  74. package/dist/src/parties/data-party.test.js.map +1 -1
  75. package/dist/src/parties/party-factory.d.ts +3 -2
  76. package/dist/src/parties/party-factory.d.ts.map +1 -1
  77. package/dist/src/parties/party-factory.js +4 -4
  78. package/dist/src/parties/party-factory.js.map +1 -1
  79. package/dist/src/parties/party-manager.d.ts +3 -3
  80. package/dist/src/parties/party-manager.d.ts.map +1 -1
  81. package/dist/src/parties/party-manager.js +6 -11
  82. package/dist/src/parties/party-manager.js.map +1 -1
  83. package/dist/src/parties/party-manager.test.js +6 -6
  84. package/dist/src/parties/party-manager.test.js.map +1 -1
  85. package/dist/src/parties/party-preferences.d.ts +1 -1
  86. package/dist/src/parties/party-preferences.d.ts.map +1 -1
  87. package/dist/src/parties/party-preferences.js +5 -5
  88. package/dist/src/parties/party-preferences.js.map +1 -1
  89. package/dist/src/pipeline/feed-muxer.js +3 -3
  90. package/dist/src/pipeline/feed-muxer.js.map +1 -1
  91. package/dist/src/pipeline/feed-muxer.test.js +4 -2
  92. package/dist/src/pipeline/feed-muxer.test.js.map +1 -1
  93. package/dist/src/pipeline/message-selector.js +2 -2
  94. package/dist/src/pipeline/message-selector.js.map +1 -1
  95. package/dist/src/pipeline/metadata-store.d.ts.map +1 -1
  96. package/dist/src/pipeline/metadata-store.js +35 -32
  97. package/dist/src/pipeline/metadata-store.js.map +1 -1
  98. package/dist/src/pipeline/party-feed-provider.js +3 -3
  99. package/dist/src/pipeline/party-feed-provider.js.map +1 -1
  100. package/dist/src/pipeline/party-pipeline.d.ts +3 -1
  101. package/dist/src/pipeline/party-pipeline.d.ts.map +1 -1
  102. package/dist/src/pipeline/party-pipeline.js +20 -18
  103. package/dist/src/pipeline/party-pipeline.js.map +1 -1
  104. package/dist/src/pipeline/party-pipeline.test.js +10 -9
  105. package/dist/src/pipeline/party-pipeline.test.js.map +1 -1
  106. package/dist/src/pipeline/party-processor.js +3 -3
  107. package/dist/src/pipeline/party-processor.js.map +1 -1
  108. package/dist/src/protocol/authenticator.test.js +53 -12
  109. package/dist/src/protocol/authenticator.test.js.map +1 -1
  110. package/dist/src/protocol/identity-credentials.d.ts +0 -1
  111. package/dist/src/protocol/identity-credentials.d.ts.map +1 -1
  112. package/dist/src/protocol/identity-credentials.js.map +1 -1
  113. package/dist/src/protocol/index.d.ts +1 -0
  114. package/dist/src/protocol/index.d.ts.map +1 -1
  115. package/dist/src/protocol/index.js +1 -0
  116. package/dist/src/protocol/index.js.map +1 -1
  117. package/dist/src/protocol/party-protocol-factory.d.ts +1 -1
  118. package/dist/src/protocol/party-protocol-factory.d.ts.map +1 -1
  119. package/dist/src/snapshots/snapshot-store.js +2 -2
  120. package/dist/src/snapshots/snapshot-store.js.map +1 -1
  121. package/dist/src/snapshots/snapshot-store.test.js +5 -1
  122. package/dist/src/snapshots/snapshot-store.test.js.map +1 -1
  123. package/dist/src/testing/testing-factories.js +2 -2
  124. package/dist/src/testing/testing-factories.js.map +1 -1
  125. package/dist/tsconfig.tsbuildinfo +1 -1
  126. package/package.json +21 -17
  127. package/src/api/index.ts +1 -0
  128. package/src/api/result-set.ts +1 -1
  129. package/src/api/subscription.ts +24 -0
  130. package/src/echo-api.test.ts +162 -0
  131. package/src/echo.test.ts +3 -3
  132. package/src/echo.ts +12 -11
  133. package/src/halo/halo-factory.ts +1 -1
  134. package/src/halo/halo-party.ts +4 -4
  135. package/src/halo/halo.test.ts +1 -3
  136. package/src/halo/halo.ts +1 -1
  137. package/src/halo/identity-manager.ts +2 -7
  138. package/src/halo/identity.ts +3 -3
  139. package/src/halo/preferences.ts +2 -1
  140. package/src/invitations/greeting-initiator.ts +1 -1
  141. package/src/invitations/greeting-responder.ts +1 -1
  142. package/src/invitations/halo-recovery-initiator.ts +1 -1
  143. package/src/invitations/invitation-descriptor.ts +1 -1
  144. package/src/invitations/invitation-factory.ts +1 -1
  145. package/src/invitations/offline-invitation-claimer.ts +1 -1
  146. package/src/packlets/database/data-mirror.ts +1 -1
  147. package/src/packlets/database/data-service-host.ts +1 -1
  148. package/src/packlets/database/data-service-router.ts +1 -1
  149. package/src/packlets/database/database-backend.ts +1 -1
  150. package/src/packlets/database/database.ts +1 -1
  151. package/src/packlets/database/item-demuxer.ts +1 -1
  152. package/src/packlets/database/item-manager.ts +6 -6
  153. package/src/packlets/database/link.ts +1 -1
  154. package/src/packlets/database/selection/result.ts +1 -1
  155. package/src/parties/data-party.test.ts +3 -1
  156. package/src/parties/data-party.ts +3 -3
  157. package/src/parties/party-factory.ts +4 -4
  158. package/src/parties/party-manager.test.ts +1 -1
  159. package/src/parties/party-manager.ts +7 -14
  160. package/src/parties/party-preferences.ts +4 -4
  161. package/src/pipeline/feed-muxer.test.ts +4 -2
  162. package/src/pipeline/feed-muxer.ts +1 -1
  163. package/src/pipeline/message-selector.ts +1 -1
  164. package/src/pipeline/metadata-store.ts +38 -29
  165. package/src/pipeline/party-feed-provider.ts +1 -1
  166. package/src/pipeline/party-pipeline.test.ts +3 -2
  167. package/src/pipeline/party-pipeline.ts +10 -7
  168. package/src/pipeline/party-processor.ts +1 -1
  169. package/src/protocol/authenticator.test.ts +102 -17
  170. package/src/protocol/identity-credentials.ts +0 -2
  171. package/src/protocol/index.ts +1 -0
  172. package/src/protocol/party-protocol-factory.ts +1 -1
  173. package/src/snapshots/snapshot-store.test.ts +5 -1
  174. package/src/snapshots/snapshot-store.ts +1 -1
  175. package/src/testing/testing-factories.ts +1 -1
@@ -2,7 +2,7 @@
2
2
  // Copyright 2020 DXOS.org
3
3
  //
4
4
 
5
- import assert from 'assert';
5
+ import assert from 'node:assert';
6
6
 
7
7
  import { ItemID, ItemType } from '@dxos/echo-protocol';
8
8
  import { Model, StateManager } from '@dxos/model-factory';
@@ -2,7 +2,7 @@
2
2
  // Copyright 2020 DXOS.org
3
3
  //
4
4
 
5
- import assert from 'assert';
5
+ import assert from 'node:assert';
6
6
 
7
7
  import { Event } from '@dxos/async';
8
8
 
@@ -5,7 +5,9 @@
5
5
  import expect from 'expect';
6
6
  import { it as test } from 'mocha';
7
7
 
8
- import { createKeyAdmitMessage, createPartyGenesisMessage, defaultSecretProvider, Keyring, KeyType, codec as haloCodec } from '@dxos/credentials';
8
+ import {
9
+ createKeyAdmitMessage, createPartyGenesisMessage, defaultSecretProvider, Keyring, KeyType, codec as haloCodec
10
+ } from '@dxos/credentials';
9
11
  import { codec } from '@dxos/echo-protocol';
10
12
  import { FeedStore } from '@dxos/feed-store';
11
13
  import { ModelFactory } from '@dxos/model-factory';
@@ -2,7 +2,7 @@
2
2
  // Copyright 2020 DXOS.org
3
3
  //
4
4
 
5
- import assert from 'assert';
5
+ import assert from 'node:assert';
6
6
 
7
7
  import { synchronized, Event } from '@dxos/async';
8
8
  import { timed } from '@dxos/debug';
@@ -30,7 +30,7 @@ export const PARTY_TITLE_PROPERTY = 'title'; // TODO(burdon): Remove (should not
30
30
 
31
31
  // TODO(burdon): Factor out public API.
32
32
  export interface PartyMember {
33
- publicKey: PublicKey,
33
+ publicKey: PublicKey
34
34
  displayName?: string
35
35
  }
36
36
 
@@ -142,7 +142,7 @@ export class DataParty {
142
142
  await this._preferences?.setLastKnownTitle(title);
143
143
  }
144
144
 
145
- get genesisFeedKey () {
145
+ get genesisFeedKey (): PublicKey {
146
146
  assert(this._genesisFeedKey);
147
147
  return this._genesisFeedKey;
148
148
  }
@@ -2,8 +2,8 @@
2
2
  // Copyright 2020 DXOS.org
3
3
  //
4
4
 
5
- import assert from 'assert';
6
5
  import debug from 'debug';
6
+ import assert from 'node:assert';
7
7
 
8
8
  import {
9
9
  createEnvelopeMessage,
@@ -19,7 +19,7 @@ import { ModelFactory } from '@dxos/model-factory';
19
19
  import { NetworkManager } from '@dxos/network-manager';
20
20
  import { ObjectModel } from '@dxos/object-model';
21
21
  import { PublicKey, Timeframe } from '@dxos/protocols';
22
- import { humanize } from '@dxos/util';
22
+ import { humanize, Provider } from '@dxos/util';
23
23
 
24
24
  import {
25
25
  createDataPartyAdmissionMessages,
@@ -27,7 +27,7 @@ import {
27
27
  } from '../invitations';
28
28
  import { IdentityNotInitializedError } from '../packlets/errors';
29
29
  import { MetadataStore, PartyFeedProvider, PipelineOptions } from '../pipeline';
30
- import { IdentityCredentialsProvider } from '../protocol/identity-credentials';
30
+ import { IdentityCredentials } from '../protocol/identity-credentials';
31
31
  import { SnapshotStore } from '../snapshots';
32
32
  import { DataParty, PARTY_ITEM_TYPE } from './data-party';
33
33
 
@@ -38,7 +38,7 @@ const log = debug('dxos:echo-db:party-factory');
38
38
  */
39
39
  export class PartyFactory {
40
40
  constructor (
41
- private readonly _identityProvider: IdentityCredentialsProvider,
41
+ private readonly _identityProvider: Provider<IdentityCredentials | undefined>,
42
42
  private readonly _networkManager: NetworkManager,
43
43
  private readonly _modelFactory: ModelFactory,
44
44
  private readonly _snapshotStore: SnapshotStore,
@@ -4,10 +4,10 @@
4
4
 
5
5
  /* eslint-disable jest/no-conditional-expect */
6
6
 
7
- import assert from 'assert';
8
7
  import debug from 'debug';
9
8
  import expect from 'expect';
10
9
  import { it as test } from 'mocha';
10
+ import assert from 'node:assert';
11
11
 
12
12
  import { latch } from '@dxos/async';
13
13
  import {
@@ -2,20 +2,20 @@
2
2
  // Copyright 2020 DXOS.org
3
3
  //
4
4
 
5
- import assert from 'assert';
6
5
  import debug from 'debug';
7
6
  import unionWith from 'lodash.unionwith';
7
+ import assert from 'node:assert';
8
8
 
9
9
  import { Event, synchronized } from '@dxos/async';
10
10
  import { SecretProvider } from '@dxos/credentials';
11
11
  import { failUndefined, timed } from '@dxos/debug';
12
12
  import { PartyKey, PartySnapshot } from '@dxos/echo-protocol';
13
13
  import { PublicKey } from '@dxos/protocols';
14
- import { ComplexMap, boolGuard } from '@dxos/util';
14
+ import { ComplexMap, boolGuard, Provider } from '@dxos/util';
15
15
 
16
16
  import { InvitationDescriptor } from '../invitations';
17
17
  import { MetadataStore } from '../pipeline';
18
- import { IdentityCredentialsProvider } from '../protocol/identity-credentials';
18
+ import { IdentityCredentials } from '../protocol/identity-credentials';
19
19
  import { SnapshotStore } from '../snapshots';
20
20
  import { DataParty, PARTY_ITEM_TYPE, PARTY_TITLE_PROPERTY } from './data-party';
21
21
  import { PartyFactory } from './party-factory';
@@ -25,9 +25,9 @@ export const CONTACT_DEBOUNCE_INTERVAL = 500;
25
25
  const log = debug('dxos:echo-db:party-manager');
26
26
 
27
27
  export interface OpenProgress {
28
- haloOpened: boolean;
29
- partiesOpened?: number;
30
- totalParties?: number;
28
+ haloOpened: boolean
29
+ partiesOpened?: number
30
+ totalParties?: number
31
31
  }
32
32
 
33
33
  /**
@@ -42,16 +42,12 @@ export class PartyManager {
42
42
  // Map of parties by party key.
43
43
  private readonly _parties = new ComplexMap<PublicKey, DataParty>(key => key.toHex());
44
44
 
45
- // Unsubscribe handlers.
46
- // TODO(burdon): Never used.
47
- private readonly _onCloseHandlers: (() => void)[] = [];
48
-
49
45
  private _open = false;
50
46
 
51
47
  constructor (
52
48
  private readonly _metadataStore: MetadataStore,
53
49
  private readonly _snapshotStore: SnapshotStore,
54
- private readonly _identityProvider: IdentityCredentialsProvider,
50
+ private readonly _identityProvider: Provider<IdentityCredentials | undefined>,
55
51
  private readonly _partyFactory: PartyFactory
56
52
  ) {}
57
53
 
@@ -129,9 +125,6 @@ export class PartyManager {
129
125
  }
130
126
  this._open = false;
131
127
 
132
- // Clean-up.
133
- this._onCloseHandlers.forEach(callback => callback());
134
-
135
128
  // Close parties.
136
129
  for (const party of this._parties.values()) {
137
130
  if (party.isOpen) {
@@ -2,14 +2,14 @@
2
2
  // Copyright 2020 DXOS.org
3
3
  //
4
4
 
5
- import assert from 'assert';
5
+ import assert from 'node:assert';
6
6
 
7
- import { PARTY_TITLE_PROPERTY, DataParty } from '.';
8
7
  import { Preferences } from '../halo/preferences';
8
+ import { PARTY_TITLE_PROPERTY, DataParty } from './data-party';
9
9
 
10
10
  export interface ActivationOptions {
11
- global?: boolean;
12
- device?: boolean;
11
+ global?: boolean
12
+ device?: boolean
13
13
  }
14
14
 
15
15
  /**
@@ -128,7 +128,8 @@ describe('FeedMuxer', () => {
128
128
  await pipeline.outboundEchoStream!.write({
129
129
  itemId: '123',
130
130
  genesis: {
131
- itemType: 'foo'
131
+ itemType: 'foo',
132
+ modelType: 'bar'
132
133
  }
133
134
  });
134
135
 
@@ -138,7 +139,8 @@ describe('FeedMuxer', () => {
138
139
  expect((echoMessages[0] as any).data).toEqual({
139
140
  itemId: '123',
140
141
  genesis: {
141
- itemType: 'foo'
142
+ itemType: 'foo',
143
+ modelType: 'bar'
142
144
  }
143
145
  });
144
146
  });
@@ -2,8 +2,8 @@
2
2
  // Copyright 2020 DXOS.org
3
3
  //
4
4
 
5
- import assert from 'assert';
6
5
  import debug from 'debug';
6
+ import assert from 'node:assert';
7
7
 
8
8
  import { Event } from '@dxos/async';
9
9
  import { Message as HaloMessage } from '@dxos/credentials';
@@ -2,8 +2,8 @@
2
2
  // Copyright 2020 DXOS.org
3
3
  //
4
4
 
5
- import assert from 'assert';
6
5
  import debug from 'debug';
6
+ import assert from 'node:assert';
7
7
 
8
8
  import { MessageSelector } from '@dxos/echo-protocol';
9
9
 
@@ -2,8 +2,8 @@
2
2
  // Copyright 2021 DXOS.org
3
3
  //
4
4
 
5
- import assert from 'assert';
6
5
  import debug from 'debug';
6
+ import assert from 'node:assert';
7
7
 
8
8
  import { synchronized } from '@dxos/async';
9
9
  import { failUndefined } from '@dxos/debug';
@@ -25,13 +25,15 @@ export interface AddPartyOptions {
25
25
  genesisFeed: PublicKey
26
26
  }
27
27
 
28
+ const emptyEchoMetadata = (): EchoMetadata => ({
29
+ version: STORAGE_VERSION,
30
+ parties: [],
31
+ created: new Date(),
32
+ updated: new Date()
33
+ });
34
+
28
35
  export class MetadataStore {
29
- private _metadata: EchoMetadata = {
30
- version: STORAGE_VERSION,
31
- parties: [],
32
- created: new Date(),
33
- updated: new Date()
34
- };
36
+ private _metadata: EchoMetadata = emptyEchoMetadata();
35
37
 
36
38
  constructor (
37
39
  private readonly _directory: Directory
@@ -56,19 +58,26 @@ export class MetadataStore {
56
58
  async load (): Promise<void> {
57
59
  const file = this._directory.createOrOpen('EchoMetadata');
58
60
  try {
59
- const { size } = await file.stat();
60
- if (size === 0) {
61
+ const { size: fileLength } = await file.stat();
62
+ if (fileLength < 4) {
61
63
  return;
62
64
  }
65
+ // Loading file size from first 4 bytes.
66
+ const dataSize = fromBytesInt32(await file.read(0, 4));
67
+ log(`Load: data size ${dataSize}`);
68
+
69
+ // Sanity check.
70
+ {
71
+ if (fileLength < dataSize + 4) {
72
+ throw new Error('Metadata storage is corrupted');
73
+ }
74
+ }
63
75
 
64
- const data = await file.read(0, size);
76
+ const data = await file.read(4, dataSize);
65
77
  this._metadata = schema.getCodecForType('dxos.echo.metadata.EchoMetadata').decode(data);
66
78
  } catch (err: any) {
67
- if (err.code === 'ENOENT') {
68
- return;
69
- } else {
70
- throw err;
71
- }
79
+ log(`Error loading metadata: ${err}`);
80
+ this._metadata = emptyEchoMetadata();
72
81
  } finally {
73
82
  await file.close();
74
83
  }
@@ -87,22 +96,14 @@ export class MetadataStore {
87
96
 
88
97
  try {
89
98
  const encoded = Buffer.from(schema.getCodecForType('dxos.echo.metadata.EchoMetadata').encode(data));
90
- await file.write(0, encoded);
91
99
 
92
- // Truncate the rest of the file.
93
- {
94
- const { size } = await file.stat();
95
- if (size > encoded.length) {
96
- await file.truncate(encoded.length, size);
97
- }
98
- }
100
+ // Saving file size at first 4 bytes.
101
+ log(`Save: data size ${encoded.length}`);
102
+ await file.write(0, toBytesInt32(encoded.length));
103
+
104
+ // Saving data.
105
+ await file.write(4, encoded);
99
106
 
100
- // Sanity check.
101
- const { size } = await file.stat();
102
- if (size !== encoded.length) {
103
- console.log('SANITY!');
104
- }
105
- assert(size === encoded.length);
106
107
  } finally {
107
108
  await file.close();
108
109
  }
@@ -196,3 +197,11 @@ export class MetadataStore {
196
197
  await this._save();
197
198
  }
198
199
  }
200
+
201
+ const toBytesInt32 = (num: number) => {
202
+ const buf = Buffer.alloc(4);
203
+ buf.writeInt32LE(num, 0);
204
+ return buf;
205
+ };
206
+
207
+ const fromBytesInt32 = (buf: Buffer) => buf.readInt32LE(0);
@@ -2,8 +2,8 @@
2
2
  // Copyright 2021 DXOS.org
3
3
  //
4
4
 
5
- import assert from 'assert';
6
5
  import debug from 'debug';
6
+ import assert from 'node:assert';
7
7
 
8
8
  import { Event, synchronized } from '@dxos/async';
9
9
  import { Keyring, KeyType } from '@dxos/credentials';
@@ -18,9 +18,10 @@ import { PublicKey, Timeframe } from '@dxos/protocols';
18
18
  import { createStorage, StorageType } from '@dxos/random-access-multi-storage';
19
19
  import { afterTest } from '@dxos/testutils';
20
20
 
21
- import { MetadataStore, PartyFeedProvider } from '.';
22
- import { createReplicatorPlugin } from '../protocol/replicator-plugin';
21
+ import { createReplicatorPlugin } from '../protocol';
23
22
  import { SnapshotStore } from '../snapshots';
23
+ import { MetadataStore } from './metadata-store';
24
+ import { PartyFeedProvider } from './party-feed-provider';
24
25
  import { PartyPipeline } from './party-pipeline';
25
26
 
26
27
  describe('PartyPipeline', () => {
@@ -2,7 +2,7 @@
2
2
  // Copyright 2021 DXOS.org
3
3
  //
4
4
 
5
- import assert from 'assert';
5
+ import assert from 'node:assert';
6
6
 
7
7
  import { synchronized } from '@dxos/async';
8
8
  import { KeyType, Message as HaloMessage } from '@dxos/credentials';
@@ -14,20 +14,23 @@ import { ModelFactory } from '@dxos/model-factory';
14
14
  import { PublicKey, Timeframe } from '@dxos/protocols';
15
15
  import { SubscriptionGroup } from '@dxos/util';
16
16
 
17
- import { createMessageSelector, PartyProcessor, PartyFeedProvider, FeedMuxer } from '.';
18
17
  import { Database, FeedDatabaseBackend, TimeframeClock } from '../packlets/database';
19
18
  import { createAutomaticSnapshots, SnapshotStore } from '../snapshots';
19
+ import { FeedMuxer } from './feed-muxer';
20
+ import { createMessageSelector } from './message-selector';
21
+ import { PartyFeedProvider } from './party-feed-provider';
22
+ import { PartyProcessor } from './party-processor';
20
23
 
21
24
  const DEFAULT_SNAPSHOT_INTERVAL = 100; // Every 100 messages.
22
25
 
23
26
  export interface PipelineOptions {
24
- readLogger?: (msg: any) => void;
25
- writeLogger?: (msg: any) => void;
26
- readOnly?: boolean;
27
+ readLogger?: (msg: any) => void
28
+ writeLogger?: (msg: any) => void
29
+ readOnly?: boolean
27
30
  // TODO(burdon): Hierarchical options.
28
31
  // snapshots: { enabled: true, interval: 100 } }
29
- snapshots?: boolean;
30
- snapshotInterval?: number;
32
+ snapshots?: boolean
33
+ snapshotInterval?: number
31
34
  }
32
35
 
33
36
  export interface OpenOptions {
@@ -2,8 +2,8 @@
2
2
  // Copyright 2020 DXOS.org
3
3
  //
4
4
 
5
- import assert from 'assert';
6
5
  import debug from 'debug';
6
+ import assert from 'node:assert';
7
7
 
8
8
  import { Event } from '@dxos/async';
9
9
  import {
@@ -5,21 +5,18 @@
5
5
  import expect from 'expect';
6
6
  import { it as test } from 'mocha';
7
7
 
8
- import { createAuthMessage, createKeyAdmitMessage, createPartyGenesisMessage, Keyring, KeyType } from '@dxos/credentials';
8
+ import { createAuthMessage, createEnvelopeMessage, createFeedAdmitMessage, createKeyAdmitMessage, createPartyGenesisMessage, Keyring, KeyType, wrapMessage } from '@dxos/credentials';
9
9
 
10
10
  import { PartyProcessor } from '../pipeline';
11
11
  import { createAuthenticator } from './authenticator';
12
- import { CredentialsSigner } from './credentials-signer';
12
+ import { createTestIdentityCredentials } from './identity-credentials';
13
13
 
14
14
  describe('authenticator', () => {
15
- // TODO(dmaretskyi): Figure out how credentials work and if this test makes sense.
16
- test.skip('authenticates admitted peer', async () => {
15
+ test('authenticates party creator', async () => {
17
16
  const keyring = new Keyring();
17
+ const identity = await createTestIdentityCredentials(keyring);
18
18
  const partyKey = await keyring.createKeyRecord({ type: KeyType.PARTY });
19
- const identityKey = await keyring.createKeyRecord({ type: KeyType.IDENTITY });
20
- const deviceKey = await keyring.createKeyRecord({ type: KeyType.DEVICE });
21
- const feedKey = await keyring.createKeyRecord({ type: KeyType.FEED });
22
- const signer = CredentialsSigner.createDirectDeviceSigner(keyring);
19
+ const feedKey = await keyring.createKeyRecord({ type: KeyType.PARTY });
23
20
 
24
21
  const partyProcessor = new PartyProcessor(partyKey.publicKey);
25
22
  await partyProcessor.processMessage({
@@ -27,16 +24,106 @@ describe('authenticator', () => {
27
24
  keyring,
28
25
  partyKey,
29
26
  feedKey.publicKey,
30
- identityKey
27
+ partyKey
31
28
  ),
32
29
  meta: {} as any
33
30
  });
31
+ await partyProcessor.processMessage({
32
+ data: createEnvelopeMessage(
33
+ identity.keyring,
34
+ partyKey.publicKey,
35
+ wrapMessage(identity.identityGenesis),
36
+ [partyKey]
37
+ ),
38
+ meta: {} as any
39
+ });
40
+ await partyProcessor.processMessage({
41
+ data: createFeedAdmitMessage(
42
+ keyring,
43
+ partyKey.publicKey,
44
+ feedKey.publicKey,
45
+ [identity.deviceKeyChain]
46
+ ),
47
+ meta: {} as any
48
+ });
49
+
50
+ const authenticator = createAuthenticator(partyProcessor, identity.createCredentialsSigner(), null as any);
51
+
52
+ //
53
+ // This test follows the same party creation routing as party factory.
54
+ // Oddly, it does not admit the device key to the party.
55
+ // This means that authentication is actually done using the signature created using the feed key.
56
+ //
57
+
58
+ // Does not authenticate without the feed key.
59
+ {
60
+ const credential = createAuthMessage(
61
+ keyring,
62
+ partyKey.publicKey,
63
+ identity.identityKey,
64
+ identity.deviceKey
65
+ );
66
+ expect(await authenticator.authenticate(credential.payload)).toEqual(false);
67
+ }
68
+
69
+ // Does authenticate with the feed key.
70
+ {
71
+ const credential = createAuthMessage(
72
+ keyring,
73
+ partyKey.publicKey,
74
+ identity.identityKey,
75
+ identity.deviceKey,
76
+ feedKey.publicKey
77
+ );
78
+ expect(await authenticator.authenticate(credential.payload)).toEqual(true);
79
+ }
80
+ });
81
+
82
+ test('authenticates another identity', async () => {
83
+ const keyring = new Keyring();
84
+ const identity = await createTestIdentityCredentials(keyring);
85
+ const partyKey = await keyring.createKeyRecord({ type: KeyType.PARTY });
86
+ const feedKey = await keyring.createKeyRecord({ type: KeyType.PARTY });
87
+
88
+ const partyProcessor = new PartyProcessor(partyKey.publicKey);
89
+ await partyProcessor.processMessage({
90
+ data: createPartyGenesisMessage(
91
+ keyring,
92
+ partyKey,
93
+ feedKey.publicKey,
94
+ partyKey
95
+ ),
96
+ meta: {} as any
97
+ });
98
+ await partyProcessor.processMessage({
99
+ data: createEnvelopeMessage(
100
+ identity.keyring,
101
+ partyKey.publicKey,
102
+ wrapMessage(identity.identityGenesis),
103
+ [partyKey]
104
+ ),
105
+ meta: {} as any
106
+ });
107
+ await partyProcessor.processMessage({
108
+ data: createFeedAdmitMessage(
109
+ keyring,
110
+ partyKey.publicKey,
111
+ feedKey.publicKey,
112
+ [identity.deviceKeyChain]
113
+ ),
114
+ meta: {} as any
115
+ });
116
+
117
+ const authenticator = createAuthenticator(partyProcessor, identity.createCredentialsSigner(), null as any);
118
+
119
+ const identity2 = await createTestIdentityCredentials(keyring);
120
+
34
121
  await partyProcessor.processMessage({
35
122
  data: createKeyAdmitMessage(
36
123
  keyring,
37
124
  partyKey.publicKey,
38
- identityKey,
39
- [partyKey, identityKey]
125
+ identity2.identityKey,
126
+ [identity.deviceKeyChain]
40
127
  ),
41
128
  meta: {} as any
42
129
  });
@@ -44,20 +131,18 @@ describe('authenticator', () => {
44
131
  data: createKeyAdmitMessage(
45
132
  keyring,
46
133
  partyKey.publicKey,
47
- deviceKey,
48
- [identityKey, deviceKey]
134
+ identity2.deviceKey,
135
+ [identity.deviceKeyChain]
49
136
  ),
50
137
  meta: {} as any
51
138
  });
52
139
 
53
- const authenticator = createAuthenticator(partyProcessor, signer, null as any);
54
140
  const credential = createAuthMessage(
55
141
  keyring,
56
142
  partyKey.publicKey,
57
- identityKey,
58
- deviceKey
143
+ identity2.identityKey,
144
+ identity2.deviceKey
59
145
  );
60
-
61
146
  expect(await authenticator.authenticate(credential.payload)).toEqual(true);
62
147
  });
63
148
  });
@@ -27,8 +27,6 @@ export interface IdentityCredentials {
27
27
  contacts: ContactManager | undefined
28
28
  }
29
29
 
30
- export type IdentityCredentialsProvider = () => IdentityCredentials | undefined
31
-
32
30
  export const createTestIdentityCredentials = async (keyring: Keyring): Promise<IdentityCredentials> => {
33
31
  const identityKey = await keyring.createKeyRecord({ type: KeyType.IDENTITY });
34
32
  const deviceKey = await keyring.createKeyRecord({ type: KeyType.DEVICE });
@@ -8,3 +8,4 @@ export * from './auth-plugin';
8
8
  export * from './halo-recovery-plugin';
9
9
  export * from './offline-invitation-plugin';
10
10
  export * from './party-protocol-factory';
11
+ export * from './replicator-plugin';
@@ -11,7 +11,7 @@ import { MMSTTopology, NetworkManager, Plugin } from '@dxos/network-manager';
11
11
  import { PresencePlugin } from '@dxos/protocol-plugin-presence';
12
12
  import { PublicKey } from '@dxos/protocols';
13
13
 
14
- import { CredentialsProvider } from '.';
14
+ import { CredentialsProvider } from './authenticator';
15
15
 
16
16
  const log = debug('dxos:echo-db:party-protocol-factory');
17
17
 
@@ -26,10 +26,14 @@ describe('SnapshotStore', () => {
26
26
 
27
27
  const snapshot: PartySnapshot = {
28
28
  partyKey: key1.asBuffer(),
29
+ halo: {
30
+ messages: []
31
+ },
29
32
  database: {
30
33
  items: [{
31
34
  itemId: createId(),
32
- itemType: 'example:test'
35
+ itemType: 'example:test',
36
+ modelType: 'example:model'
33
37
  }],
34
38
  links: []
35
39
  }
@@ -2,8 +2,8 @@
2
2
  // Copyright 2020 DXOS.org
3
3
  //
4
4
 
5
- import assert from 'assert';
6
5
  import debug from 'debug';
6
+ import assert from 'node:assert';
7
7
 
8
8
  import { schema, PartyKey, PartySnapshot } from '@dxos/echo-protocol';
9
9
  import { PublicKey } from '@dxos/protocols';
@@ -2,7 +2,7 @@
2
2
  // Copyright 2020 DXOS.org
3
3
  //
4
4
 
5
- import assert from 'assert';
5
+ import assert from 'node:assert';
6
6
 
7
7
  import { Model } from '@dxos/model-factory';
8
8
  import { ObjectModel } from '@dxos/object-model';