@dxos/echo-db 2.33.2-dev.8bbf1b5a → 2.33.2
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.
- package/dist/src/echo.d.ts +8 -8
- package/dist/src/echo.d.ts.map +1 -1
- package/dist/src/echo.js +15 -16
- package/dist/src/echo.js.map +1 -1
- package/dist/src/echo.test.js +7 -13
- package/dist/src/echo.test.js.map +1 -1
- package/dist/src/halo/contact-manager.d.ts +4 -4
- package/dist/src/halo/contact-manager.d.ts.map +1 -1
- package/dist/src/halo/contact-manager.js +10 -4
- package/dist/src/halo/contact-manager.js.map +1 -1
- package/dist/src/halo/halo-factory.d.ts +14 -9
- package/dist/src/halo/halo-factory.d.ts.map +1 -1
- package/dist/src/halo/halo-factory.js +47 -14
- package/dist/src/halo/halo-factory.js.map +1 -1
- package/dist/src/halo/halo-party.d.ts +35 -7
- package/dist/src/halo/halo-party.d.ts.map +1 -1
- package/dist/src/halo/halo-party.js +97 -18
- package/dist/src/halo/halo-party.js.map +1 -1
- package/dist/src/halo/halo.d.ts +14 -12
- package/dist/src/halo/halo.d.ts.map +1 -1
- package/dist/src/halo/halo.js +31 -29
- package/dist/src/halo/halo.js.map +1 -1
- package/dist/src/halo/halo.test.d.ts +2 -0
- package/dist/src/halo/halo.test.d.ts.map +1 -0
- package/dist/src/halo/halo.test.js +162 -0
- package/dist/src/halo/halo.test.js.map +1 -0
- package/dist/src/halo/identity-manager.d.ts +10 -8
- package/dist/src/halo/identity-manager.d.ts.map +1 -1
- package/dist/src/halo/identity-manager.js +24 -20
- package/dist/src/halo/identity-manager.js.map +1 -1
- package/dist/src/halo/identity.d.ts +12 -6
- package/dist/src/halo/identity.d.ts.map +1 -1
- package/dist/src/halo/identity.js +11 -15
- package/dist/src/halo/identity.js.map +1 -1
- package/dist/src/halo/index.d.ts +1 -1
- package/dist/src/halo/index.d.ts.map +1 -1
- package/dist/src/halo/index.js +1 -1
- package/dist/src/halo/index.js.map +1 -1
- package/dist/src/halo/party-opener.js +1 -1
- package/dist/src/halo/party-opener.js.map +1 -1
- package/dist/src/halo/preferences.d.ts +9 -9
- package/dist/src/halo/preferences.d.ts.map +1 -1
- package/dist/src/halo/preferences.js +25 -15
- package/dist/src/halo/preferences.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/invitations/greeting-initiator.d.ts +14 -4
- package/dist/src/invitations/greeting-initiator.d.ts.map +1 -1
- package/dist/src/invitations/greeting-initiator.js +15 -16
- package/dist/src/invitations/greeting-initiator.js.map +1 -1
- package/dist/src/invitations/greeting-responder.d.ts +3 -3
- package/dist/src/invitations/greeting-responder.d.ts.map +1 -1
- package/dist/src/invitations/greeting-responder.js +3 -4
- package/dist/src/invitations/greeting-responder.js.map +1 -1
- package/dist/src/invitations/halo-recovery-initiator.d.ts +6 -4
- package/dist/src/invitations/halo-recovery-initiator.d.ts.map +1 -1
- package/dist/src/invitations/halo-recovery-initiator.js +15 -26
- package/dist/src/invitations/halo-recovery-initiator.js.map +1 -1
- package/dist/src/invitations/index.d.ts +1 -1
- package/dist/src/invitations/index.js +1 -1
- package/dist/src/invitations/{invitation-manager.d.ts → invitation-factory.d.ts} +5 -6
- package/dist/src/invitations/invitation-factory.d.ts.map +1 -0
- package/dist/src/invitations/{invitation-manager.js → invitation-factory.js} +9 -15
- package/dist/src/invitations/invitation-factory.js.map +1 -0
- package/dist/src/invitations/offline-invitation-claimer.d.ts +3 -3
- package/dist/src/invitations/offline-invitation-claimer.js +1 -1
- package/dist/src/parties/{party-internal.d.ts → data-party.d.ts} +13 -11
- package/dist/src/parties/data-party.d.ts.map +1 -0
- package/dist/src/parties/{party-internal.js → data-party.js} +27 -37
- package/dist/src/parties/data-party.js.map +1 -0
- package/dist/src/parties/index.d.ts +1 -2
- package/dist/src/parties/index.d.ts.map +1 -1
- package/dist/src/parties/index.js +1 -2
- package/dist/src/parties/index.js.map +1 -1
- package/dist/src/parties/party-factory.d.ts +10 -11
- package/dist/src/parties/party-factory.d.ts.map +1 -1
- package/dist/src/parties/party-factory.js +25 -16
- package/dist/src/parties/party-factory.js.map +1 -1
- package/dist/src/parties/party-manager.d.ts +9 -9
- package/dist/src/parties/party-manager.d.ts.map +1 -1
- package/dist/src/parties/party-manager.js +13 -13
- package/dist/src/parties/party-manager.js.map +1 -1
- package/dist/src/parties/party-manager.test.js +69 -68
- package/dist/src/parties/party-manager.test.js.map +1 -1
- package/dist/src/{halo → parties}/party-preferences.d.ts +3 -3
- package/dist/src/parties/party-preferences.d.ts.map +1 -0
- package/dist/src/{halo → parties}/party-preferences.js +3 -3
- package/dist/src/parties/party-preferences.js.map +1 -0
- package/dist/src/pipeline/index.d.ts +3 -1
- package/dist/src/pipeline/index.d.ts.map +1 -1
- package/dist/src/pipeline/index.js +3 -1
- package/dist/src/pipeline/index.js.map +1 -1
- package/dist/src/{metadata → pipeline}/metadata-store.d.ts +0 -0
- package/dist/src/{metadata → pipeline}/metadata-store.d.ts.map +1 -1
- package/dist/src/{metadata → pipeline}/metadata-store.js +0 -0
- package/dist/src/{metadata → pipeline}/metadata-store.js.map +1 -1
- package/dist/src/{metadata → pipeline}/metadata-store.test.d.ts +0 -0
- package/dist/src/pipeline/metadata-store.test.d.ts.map +1 -0
- package/dist/src/{metadata → pipeline}/metadata-store.test.js +0 -0
- package/dist/src/{metadata → pipeline}/metadata-store.test.js.map +1 -1
- package/dist/src/{parties → pipeline}/party-core.d.ts +0 -0
- package/dist/src/pipeline/party-core.d.ts.map +1 -0
- package/dist/src/{parties → pipeline}/party-core.js +8 -4
- package/dist/src/pipeline/party-core.js.map +1 -0
- package/dist/src/{parties → pipeline}/party-core.test.d.ts +0 -0
- package/dist/src/pipeline/party-core.test.d.ts.map +1 -0
- package/dist/src/{parties → pipeline}/party-core.test.js +3 -4
- package/dist/src/pipeline/party-core.test.js.map +1 -0
- package/dist/src/pipeline/party-feed-provider.d.ts +3 -2
- package/dist/src/pipeline/party-feed-provider.d.ts.map +1 -1
- package/dist/src/pipeline/party-feed-provider.js +40 -19
- package/dist/src/pipeline/party-feed-provider.js.map +1 -1
- package/dist/src/protocol/auth-plugin.d.ts +7 -0
- package/dist/src/protocol/auth-plugin.d.ts.map +1 -0
- package/dist/src/protocol/auth-plugin.js +16 -0
- package/dist/src/protocol/auth-plugin.js.map +1 -0
- package/dist/src/protocol/authenticator.d.ts +14 -0
- package/dist/src/protocol/authenticator.d.ts.map +1 -0
- package/dist/src/protocol/authenticator.js +31 -0
- package/dist/src/protocol/authenticator.js.map +1 -0
- package/dist/src/protocol/authenticator.test.d.ts +2 -0
- package/dist/src/protocol/authenticator.test.d.ts.map +1 -0
- package/dist/src/protocol/authenticator.test.js +45 -0
- package/dist/src/protocol/authenticator.test.js.map +1 -0
- package/dist/src/protocol/credentials-signer.d.ts +31 -0
- package/dist/src/protocol/credentials-signer.d.ts.map +1 -0
- package/dist/src/protocol/credentials-signer.js +53 -0
- package/dist/src/protocol/credentials-signer.js.map +1 -0
- package/dist/src/protocol/halo-recovery-plugin.d.ts +10 -0
- package/dist/src/protocol/halo-recovery-plugin.d.ts.map +1 -0
- package/dist/src/protocol/halo-recovery-plugin.js +18 -0
- package/dist/src/protocol/halo-recovery-plugin.js.map +1 -0
- package/dist/src/protocol/index.d.ts +7 -0
- package/dist/src/protocol/index.d.ts.map +1 -0
- package/dist/src/{metadata → protocol}/index.js +7 -2
- package/dist/src/protocol/index.js.map +1 -0
- package/dist/src/protocol/offline-invitation-plugin.d.ts +9 -0
- package/dist/src/protocol/offline-invitation-plugin.d.ts.map +1 -0
- package/dist/src/protocol/offline-invitation-plugin.js +17 -0
- package/dist/src/protocol/offline-invitation-plugin.js.map +1 -0
- package/dist/src/{pipeline → protocol}/party-protocol-factory.d.ts +7 -17
- package/dist/src/protocol/party-protocol-factory.d.ts.map +1 -0
- package/dist/src/{pipeline → protocol}/party-protocol-factory.js +7 -47
- package/dist/src/protocol/party-protocol-factory.js.map +1 -0
- package/dist/src/snapshots/snapshot-generator.d.ts +1 -1
- package/dist/src/snapshots/snapshot-generator.d.ts.map +1 -1
- package/dist/src/testing/testing-factories.js.map +1 -1
- package/dist/src/testing/testing.d.ts +2 -2
- package/dist/src/testing/testing.d.ts.map +1 -1
- package/dist/src/testing/testing.js +1 -7
- package/dist/src/testing/testing.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +20 -20
- package/src/echo.test.ts +8 -14
- package/src/echo.ts +107 -109
- package/src/halo/contact-manager.ts +9 -5
- package/src/halo/halo-factory.ts +82 -19
- package/src/halo/halo-party.ts +137 -21
- package/src/halo/halo.test.ts +198 -0
- package/src/halo/halo.ts +40 -38
- package/src/halo/identity-manager.ts +33 -28
- package/src/halo/identity.ts +19 -23
- package/src/halo/index.ts +1 -1
- package/src/halo/party-opener.ts +1 -1
- package/src/halo/preferences.ts +29 -18
- package/src/index.ts +1 -1
- package/src/invitations/greeting-initiator.ts +37 -32
- package/src/invitations/greeting-responder.ts +4 -5
- package/src/invitations/halo-recovery-initiator.ts +16 -24
- package/src/invitations/index.ts +1 -1
- package/src/invitations/{invitation-manager.ts → invitation-factory.ts} +8 -15
- package/src/invitations/offline-invitation-claimer.ts +3 -3
- package/src/parties/{party-internal.ts → data-party.ts} +30 -55
- package/src/parties/index.ts +1 -2
- package/src/parties/party-factory.ts +31 -21
- package/src/parties/party-manager.test.ts +99 -73
- package/src/parties/party-manager.ts +17 -17
- package/src/{halo → parties}/party-preferences.ts +3 -3
- package/src/pipeline/index.ts +3 -1
- package/src/{metadata → pipeline}/metadata-store.test.ts +0 -0
- package/src/{metadata → pipeline}/metadata-store.ts +0 -0
- package/src/{parties → pipeline}/party-core.test.ts +1 -2
- package/src/{parties → pipeline}/party-core.ts +12 -7
- package/src/pipeline/party-feed-provider.ts +32 -21
- package/src/protocol/auth-plugin.ts +14 -0
- package/src/protocol/authenticator.test.ts +66 -0
- package/src/protocol/authenticator.ts +56 -0
- package/src/protocol/credentials-signer.ts +60 -0
- package/src/protocol/halo-recovery-plugin.ts +20 -0
- package/src/protocol/index.ts +10 -0
- package/src/protocol/offline-invitation-plugin.ts +19 -0
- package/src/{pipeline → protocol}/party-protocol-factory.ts +10 -82
- package/src/snapshots/snapshot-generator.ts +1 -1
- package/src/testing/testing-factories.ts +2 -2
- package/src/testing/testing.ts +3 -9
- package/dist/src/halo/party-preferences.d.ts.map +0 -1
- package/dist/src/halo/party-preferences.js.map +0 -1
- package/dist/src/invitations/invitation-manager.d.ts.map +0 -1
- package/dist/src/invitations/invitation-manager.js.map +0 -1
- package/dist/src/metadata/index.d.ts +0 -2
- package/dist/src/metadata/index.d.ts.map +0 -1
- package/dist/src/metadata/index.js.map +0 -1
- package/dist/src/metadata/metadata-store.test.d.ts.map +0 -1
- package/dist/src/parties/authenticator.d.ts +0 -5
- package/dist/src/parties/authenticator.d.ts.map +0 -1
- package/dist/src/parties/authenticator.js +0 -27
- package/dist/src/parties/authenticator.js.map +0 -1
- package/dist/src/parties/party-core.d.ts.map +0 -1
- package/dist/src/parties/party-core.js.map +0 -1
- package/dist/src/parties/party-core.test.d.ts.map +0 -1
- package/dist/src/parties/party-core.test.js.map +0 -1
- package/dist/src/parties/party-internal.d.ts.map +0 -1
- package/dist/src/parties/party-internal.js.map +0 -1
- package/dist/src/pipeline/party-protocol-factory.d.ts.map +0 -1
- package/dist/src/pipeline/party-protocol-factory.js.map +0 -1
- package/src/metadata/index.ts +0 -5
- package/src/parties/authenticator.ts +0 -31
package/src/echo.test.ts
CHANGED
|
@@ -9,7 +9,7 @@ import { it as test } from 'mocha';
|
|
|
9
9
|
|
|
10
10
|
import { latch, promiseTimeout, waitForCondition } from '@dxos/async';
|
|
11
11
|
import { defaultSecretProvider, defaultSecretValidator } from '@dxos/credentials';
|
|
12
|
-
import { generateSeedPhrase, keyPairFromSeedPhrase
|
|
12
|
+
import { generateSeedPhrase, keyPairFromSeedPhrase } from '@dxos/crypto';
|
|
13
13
|
import { ObjectModel } from '@dxos/object-model';
|
|
14
14
|
import { afterTest } from '@dxos/testutils';
|
|
15
15
|
|
|
@@ -34,8 +34,7 @@ describe('ECHO', () => {
|
|
|
34
34
|
afterTest(() => echo.close());
|
|
35
35
|
|
|
36
36
|
if (createProfile) {
|
|
37
|
-
await echo.halo.
|
|
38
|
-
await echo.halo.create(displayName); // TODO(burdon): Rename.
|
|
37
|
+
await echo.halo.createProfile({ username: displayName });
|
|
39
38
|
}
|
|
40
39
|
|
|
41
40
|
return echo;
|
|
@@ -227,8 +226,7 @@ describe('ECHO', () => {
|
|
|
227
226
|
test('open and create profile', async () => {
|
|
228
227
|
const echo = new ECHO();
|
|
229
228
|
await echo.open();
|
|
230
|
-
await echo.halo.
|
|
231
|
-
await echo.halo.create();
|
|
229
|
+
await echo.halo.createProfile();
|
|
232
230
|
expect(echo.halo.identityKey).toBeDefined();
|
|
233
231
|
await echo.close();
|
|
234
232
|
});
|
|
@@ -236,8 +234,7 @@ describe('ECHO', () => {
|
|
|
236
234
|
test('close and open again', async () => {
|
|
237
235
|
const echo = new ECHO();
|
|
238
236
|
await echo.open();
|
|
239
|
-
await echo.halo.
|
|
240
|
-
await echo.halo.create();
|
|
237
|
+
await echo.halo.createProfile();
|
|
241
238
|
expect(echo.halo.identityKey).toBeDefined();
|
|
242
239
|
await echo.close();
|
|
243
240
|
|
|
@@ -256,8 +253,7 @@ describe('ECHO', () => {
|
|
|
256
253
|
test('reset', async () => {
|
|
257
254
|
const echo = new ECHO();
|
|
258
255
|
await echo.open();
|
|
259
|
-
await echo.halo.
|
|
260
|
-
await echo.halo.create();
|
|
256
|
+
await echo.halo.createProfile();
|
|
261
257
|
expect(echo.halo.identityKey).toBeDefined();
|
|
262
258
|
|
|
263
259
|
await echo.reset();
|
|
@@ -376,7 +372,7 @@ describe('ECHO', () => {
|
|
|
376
372
|
|
|
377
373
|
}).timeout(10_000);
|
|
378
374
|
|
|
379
|
-
test('3 devices', async () => {
|
|
375
|
+
test.skip('3 devices', async () => {
|
|
380
376
|
const a = await setup({ createProfile: true });
|
|
381
377
|
const b = await setup();
|
|
382
378
|
|
|
@@ -529,8 +525,7 @@ describe('ECHO', () => {
|
|
|
529
525
|
afterTest(() => a.close());
|
|
530
526
|
|
|
531
527
|
const seedPhrase = generateSeedPhrase();
|
|
532
|
-
await a.halo.
|
|
533
|
-
await a.halo.create();
|
|
528
|
+
await a.halo.createProfile({ ...keyPairFromSeedPhrase(seedPhrase) });
|
|
534
529
|
|
|
535
530
|
const b = await setup();
|
|
536
531
|
|
|
@@ -760,8 +755,7 @@ describe('ECHO', () => {
|
|
|
760
755
|
afterTest(() => a.close());
|
|
761
756
|
|
|
762
757
|
const seedPhrase = generateSeedPhrase();
|
|
763
|
-
await a.halo.
|
|
764
|
-
await a.halo.create();
|
|
758
|
+
await a.halo.createProfile({ ...keyPairFromSeedPhrase(seedPhrase) });
|
|
765
759
|
|
|
766
760
|
// User's other device, joined by device invitation.
|
|
767
761
|
const b = await setup();
|
package/src/echo.ts
CHANGED
|
@@ -9,7 +9,7 @@ import memdown from 'memdown';
|
|
|
9
9
|
import { synchronized } from '@dxos/async';
|
|
10
10
|
import { Keyring, KeyStore, SecretProvider } from '@dxos/credentials';
|
|
11
11
|
import { PublicKey } from '@dxos/crypto';
|
|
12
|
-
import { InvalidStateError } from '@dxos/debug';
|
|
12
|
+
import { InvalidStateError, raise } from '@dxos/debug';
|
|
13
13
|
import { codec, DataService, PartyKey, PartySnapshot } from '@dxos/echo-protocol';
|
|
14
14
|
import { FeedStore } from '@dxos/feed-store';
|
|
15
15
|
import { ModelFactory } from '@dxos/model-factory';
|
|
@@ -20,13 +20,12 @@ import { SubscriptionGroup } from '@dxos/util';
|
|
|
20
20
|
|
|
21
21
|
import { ResultSet } from './api';
|
|
22
22
|
import { DataServiceRouter } from './database';
|
|
23
|
-
import { InvalidStorageVersionError } from './errors';
|
|
23
|
+
import { IdentityNotInitializedError, InvalidStorageVersionError } from './errors';
|
|
24
24
|
import { HALO } from './halo';
|
|
25
25
|
import { autoPartyOpener } from './halo/party-opener';
|
|
26
26
|
import { InvitationDescriptor, OfflineInvitationClaimer } from './invitations';
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import { PartyFeedProvider } from './pipeline';
|
|
27
|
+
import { OpenProgress, PartyFactory, DataParty, PartyManager } from './parties';
|
|
28
|
+
import { MetadataStore, STORAGE_VERSION, PartyFeedProvider } from './pipeline';
|
|
30
29
|
import { SnapshotStore } from './snapshots';
|
|
31
30
|
import { createRamStorage } from './util';
|
|
32
31
|
|
|
@@ -34,7 +33,7 @@ const log = debug('dxos:echo');
|
|
|
34
33
|
const error = log.extend('error');
|
|
35
34
|
|
|
36
35
|
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
|
37
|
-
export interface PartyFilter {}
|
|
36
|
+
export interface PartyFilter { }
|
|
38
37
|
|
|
39
38
|
/**
|
|
40
39
|
* Various options passed to `ECHO.create`.
|
|
@@ -133,7 +132,7 @@ export class ECHO {
|
|
|
133
132
|
this._keyring = new Keyring(new KeyStore(keyStorage));
|
|
134
133
|
this._feedStore = new FeedStore(feedStorage, { valueEncoding: codec });
|
|
135
134
|
|
|
136
|
-
const
|
|
135
|
+
const feedProviderFactory = (partyKey: PublicKey) => new PartyFeedProvider(
|
|
137
136
|
this._metadataStore,
|
|
138
137
|
this._keyring,
|
|
139
138
|
this._feedStore,
|
|
@@ -153,7 +152,7 @@ export class ECHO {
|
|
|
153
152
|
this._networkManager,
|
|
154
153
|
this._modelFactory,
|
|
155
154
|
this._snapshotStore,
|
|
156
|
-
|
|
155
|
+
feedProviderFactory,
|
|
157
156
|
options
|
|
158
157
|
);
|
|
159
158
|
|
|
@@ -164,18 +163,19 @@ export class ECHO {
|
|
|
164
163
|
partyFactory
|
|
165
164
|
);
|
|
166
165
|
|
|
167
|
-
// TODO(burdon): Why does this need both PartyManager and PartyFactory?
|
|
168
166
|
this._halo = new HALO({
|
|
169
167
|
keyring: this._keyring,
|
|
170
|
-
partyManager: this._partyManager,
|
|
171
|
-
partyFactory,
|
|
172
168
|
networkManager: this._networkManager,
|
|
173
|
-
metadataStore: this._metadataStore
|
|
169
|
+
metadataStore: this._metadataStore,
|
|
170
|
+
feedProviderFactory: feedProviderFactory,
|
|
171
|
+
modelFactory: this._modelFactory,
|
|
172
|
+
snapshotStore: this._snapshotStore,
|
|
173
|
+
options
|
|
174
174
|
});
|
|
175
175
|
|
|
176
176
|
this._halo.identityReady.once(() => {
|
|
177
177
|
// It might be the case that halo gets closed before this has a chance to execute.
|
|
178
|
-
if (this.halo.identity.
|
|
178
|
+
if (this.halo.identity?.halo.isOpen) {
|
|
179
179
|
this._subs.push(autoPartyOpener(this.halo.identity.preferences!, this._partyManager));
|
|
180
180
|
}
|
|
181
181
|
});
|
|
@@ -260,7 +260,7 @@ export class ECHO {
|
|
|
260
260
|
/**
|
|
261
261
|
* Closes the ECHO instance.
|
|
262
262
|
*/
|
|
263
|
-
|
|
263
|
+
@synchronized
|
|
264
264
|
async close () {
|
|
265
265
|
if (!this.isOpen) {
|
|
266
266
|
return;
|
|
@@ -268,10 +268,8 @@ export class ECHO {
|
|
|
268
268
|
|
|
269
269
|
this._subs.unsubscribe();
|
|
270
270
|
|
|
271
|
-
// TODO(marik-d): Should be `_identityManager.close()`.
|
|
272
271
|
await this.halo.close();
|
|
273
272
|
|
|
274
|
-
// TODO(marik-d): Close network manager.
|
|
275
273
|
await this._partyManager.close();
|
|
276
274
|
|
|
277
275
|
await this._feedStore.close();
|
|
@@ -279,107 +277,107 @@ export class ECHO {
|
|
|
279
277
|
await this.networkManager.destroy();
|
|
280
278
|
}
|
|
281
279
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
280
|
+
/**
|
|
281
|
+
* Removes all data and closes this ECHO instance.
|
|
282
|
+
*
|
|
283
|
+
* The instance will be in an unusable state at this point and a page refresh is recommended.
|
|
284
|
+
*/
|
|
285
|
+
// TODO(burdon): Enable re-open.
|
|
286
|
+
async reset () {
|
|
287
|
+
await this.close();
|
|
288
|
+
|
|
289
|
+
try {
|
|
290
|
+
if (this._feedStore.storage.destroy) {
|
|
291
|
+
await this._feedStore.storage.destroy();
|
|
292
|
+
}
|
|
293
|
+
} catch (err: any) {
|
|
294
|
+
error('Error clearing feed storage:', err);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
await this.halo.reset();
|
|
298
|
+
|
|
299
|
+
try {
|
|
300
|
+
await this._snapshotStore.clear();
|
|
301
|
+
} catch (err: any) {
|
|
302
|
+
error('Error clearing snapshot storage:', err);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
try {
|
|
306
|
+
await this._metadataStore.clear();
|
|
307
|
+
} catch (err: any) {
|
|
308
|
+
error('Error clearing metadata storage:', err);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
//
|
|
313
|
+
// Parties.
|
|
314
|
+
//
|
|
315
|
+
|
|
316
|
+
/**
|
|
319
317
|
* Creates a new party.
|
|
320
318
|
*/
|
|
321
|
-
|
|
322
|
-
|
|
319
|
+
async createParty (): Promise<DataParty> {
|
|
320
|
+
await this.open();
|
|
321
|
+
|
|
322
|
+
const party = await this._partyManager.createParty();
|
|
323
|
+
await party.open();
|
|
323
324
|
|
|
324
|
-
|
|
325
|
-
|
|
325
|
+
return party;
|
|
326
|
+
}
|
|
326
327
|
|
|
327
|
-
|
|
328
|
-
|
|
328
|
+
/**
|
|
329
|
+
* Clones an existing party from a snapshot.
|
|
330
|
+
* @param snapshot
|
|
331
|
+
*/
|
|
332
|
+
async cloneParty (snapshot: PartySnapshot) {
|
|
333
|
+
await this.open();
|
|
329
334
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
* @param snapshot
|
|
333
|
-
*/
|
|
334
|
-
async cloneParty (snapshot: PartySnapshot) {
|
|
335
|
-
await this.open();
|
|
335
|
+
const party = await this._partyManager.cloneParty(snapshot);
|
|
336
|
+
await party.open();
|
|
336
337
|
|
|
337
|
-
|
|
338
|
-
|
|
338
|
+
return party;
|
|
339
|
+
}
|
|
339
340
|
|
|
340
|
-
|
|
341
|
-
|
|
341
|
+
/**
|
|
342
|
+
* Returns an individual party by it's key.
|
|
343
|
+
* @param {PartyKey} partyKey
|
|
344
|
+
*/
|
|
345
|
+
getParty (partyKey: PartyKey): DataParty | undefined {
|
|
346
|
+
if (!this._partyManager.isOpen) {
|
|
347
|
+
throw new InvalidStateError();
|
|
348
|
+
}
|
|
342
349
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
*/
|
|
347
|
-
getParty (partyKey: PartyKey): PartyInternal | undefined {
|
|
348
|
-
if (!this._partyManager.isOpen) {
|
|
349
|
-
throw new InvalidStateError();
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
const party = this._partyManager.parties.find(party => party.key.equals(partyKey));
|
|
353
|
-
return party;
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
/**
|
|
357
|
-
* Queries for a set of Parties matching the optional filter.
|
|
358
|
-
* @param {PartyFilter} filter
|
|
359
|
-
*/
|
|
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
|
-
/**
|
|
373
|
-
* Joins a party that was created by another peer and starts replicating with it.
|
|
374
|
-
* @param invitationDescriptor Invitation descriptor passed from another peer.
|
|
375
|
-
* @param secretProvider Shared secret provider, the other peer creating the invitation must have the same secret.
|
|
376
|
-
*/
|
|
377
|
-
async joinParty (invitationDescriptor: InvitationDescriptor, secretProvider?: SecretProvider): Promise<PartyInternal> {
|
|
378
|
-
assert(this._partyManager.isOpen, new InvalidStateError());
|
|
350
|
+
const party = this._partyManager.parties.find(party => party.key.equals(partyKey));
|
|
351
|
+
return party;
|
|
352
|
+
}
|
|
379
353
|
|
|
380
|
-
|
|
381
|
-
|
|
354
|
+
/**
|
|
355
|
+
* Queries for a set of Parties matching the optional filter.
|
|
356
|
+
* @param {PartyFilter} filter
|
|
357
|
+
*/
|
|
358
|
+
// eslint-disable-next-line unused-imports/no-unused-vars
|
|
359
|
+
queryParties (filter?: PartyFilter): ResultSet<DataParty> {
|
|
360
|
+
if (!this._partyManager.isOpen) {
|
|
361
|
+
throw new InvalidStateError();
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
return new ResultSet(
|
|
365
|
+
this._partyManager.update.discardParameter(),
|
|
366
|
+
() => this._partyManager.parties
|
|
367
|
+
);
|
|
368
|
+
}
|
|
382
369
|
|
|
383
|
-
|
|
384
|
-
|
|
370
|
+
/**
|
|
371
|
+
* Joins a party that was created by another peer and starts replicating with it.
|
|
372
|
+
* @param invitationDescriptor Invitation descriptor passed from another peer.
|
|
373
|
+
* @param secretProvider Shared secret provider, the other peer creating the invitation must have the same secret.
|
|
374
|
+
*/
|
|
375
|
+
async joinParty (invitationDescriptor: InvitationDescriptor, secretProvider?: SecretProvider): Promise<DataParty> {
|
|
376
|
+
assert(this._partyManager.isOpen, new InvalidStateError());
|
|
377
|
+
|
|
378
|
+
const actualSecretProvider =
|
|
379
|
+
secretProvider ?? OfflineInvitationClaimer.createSecretProvider(this.halo.identity ?? raise(new IdentityNotInitializedError()));
|
|
380
|
+
|
|
381
|
+
return this._partyManager.joinParty(invitationDescriptor, actualSecretProvider);
|
|
382
|
+
}
|
|
385
383
|
}
|
|
@@ -4,10 +4,12 @@
|
|
|
4
4
|
|
|
5
5
|
import { Event } from '@dxos/async';
|
|
6
6
|
import { PublicKey } from '@dxos/crypto';
|
|
7
|
+
import { raise } from '@dxos/debug';
|
|
7
8
|
import { ObjectModel } from '@dxos/object-model';
|
|
8
9
|
|
|
9
|
-
import { Item, ResultSet } from '../api';
|
|
10
|
-
import {
|
|
10
|
+
import { Database, Item, ResultSet } from '../api';
|
|
11
|
+
import { IdentityNotInitializedError } from '../errors';
|
|
12
|
+
import { PartyMember } from '../parties';
|
|
11
13
|
import { HALO_PARTY_CONTACT_LIST_TYPE } from './halo-party';
|
|
12
14
|
|
|
13
15
|
// TODO(burdon): Create different class (additional properties).
|
|
@@ -18,16 +20,18 @@ export type Contact = PartyMember;
|
|
|
18
20
|
*/
|
|
19
21
|
export class ContactManager {
|
|
20
22
|
constructor (
|
|
21
|
-
private readonly
|
|
23
|
+
private readonly _getDatabase: () => Database | undefined
|
|
22
24
|
) {}
|
|
23
25
|
|
|
24
26
|
getContactListItem (): Item<ObjectModel> | undefined {
|
|
25
|
-
|
|
27
|
+
const database = this._getDatabase() ?? raise(new IdentityNotInitializedError());
|
|
28
|
+
return database.select({ type: HALO_PARTY_CONTACT_LIST_TYPE }).exec().entities[0];
|
|
26
29
|
}
|
|
27
30
|
|
|
28
31
|
queryContacts (): ResultSet<Contact> {
|
|
32
|
+
const database = this._getDatabase() ?? raise(new IdentityNotInitializedError());
|
|
29
33
|
const event = new Event();
|
|
30
|
-
const result =
|
|
34
|
+
const result = database.select({ type: HALO_PARTY_CONTACT_LIST_TYPE }).exec();
|
|
31
35
|
result.update.on(() => {
|
|
32
36
|
event.emit();
|
|
33
37
|
});
|
package/src/halo/halo-factory.ts
CHANGED
|
@@ -13,18 +13,24 @@ import {
|
|
|
13
13
|
Keyring,
|
|
14
14
|
KeyType,
|
|
15
15
|
Filter,
|
|
16
|
-
SecretProvider
|
|
16
|
+
SecretProvider,
|
|
17
|
+
KeyHint,
|
|
18
|
+
createFeedAdmitMessage
|
|
17
19
|
} from '@dxos/credentials';
|
|
18
20
|
import { keyToString, PublicKey, keyPairFromSeedPhrase } from '@dxos/crypto';
|
|
21
|
+
import { ModelFactory } from '@dxos/model-factory';
|
|
19
22
|
import { NetworkManager } from '@dxos/network-manager';
|
|
20
23
|
import { ObjectModel } from '@dxos/object-model';
|
|
21
24
|
|
|
22
|
-
import { HaloRecoveryInitiator, InvitationDescriptor } from '../invitations';
|
|
23
|
-
import {
|
|
25
|
+
import { createHaloPartyAdmissionMessage, GreetingInitiator, HaloRecoveryInitiator, InvitationDescriptor, InvitationDescriptorType, OfflineInvitationClaimer } from '../invitations';
|
|
26
|
+
import { PARTY_ITEM_TYPE } from '../parties';
|
|
27
|
+
import { PartyFeedProvider, PartyOptions } from '../pipeline';
|
|
28
|
+
import { CredentialsSigner } from '../protocol/credentials-signer';
|
|
29
|
+
import { SnapshotStore } from '../snapshots';
|
|
24
30
|
import {
|
|
31
|
+
HaloParty,
|
|
25
32
|
HALO_PARTY_CONTACT_LIST_TYPE, HALO_PARTY_DEVICE_PREFERENCES_TYPE, HALO_PARTY_PREFERENCES_TYPE
|
|
26
33
|
} from './halo-party';
|
|
27
|
-
import { Identity } from './identity';
|
|
28
34
|
|
|
29
35
|
/**
|
|
30
36
|
* Options allowed when creating the HALO.
|
|
@@ -41,16 +47,32 @@ const log = debug('dxos:echo-db:halo-factory');
|
|
|
41
47
|
*/
|
|
42
48
|
export class HaloFactory {
|
|
43
49
|
constructor (
|
|
44
|
-
private readonly _partyFactory: PartyFactory,
|
|
45
50
|
private readonly _networkManager: NetworkManager,
|
|
46
|
-
private readonly
|
|
51
|
+
private readonly _modelFactory: ModelFactory,
|
|
52
|
+
private readonly _snapshotStore: SnapshotStore,
|
|
53
|
+
private readonly _feedProviderFactory: (partyKey: PublicKey) => PartyFeedProvider,
|
|
54
|
+
private readonly _keyring: Keyring,
|
|
55
|
+
private readonly _options: PartyOptions = {}
|
|
47
56
|
) {}
|
|
48
57
|
|
|
49
|
-
async constructParty (
|
|
50
|
-
|
|
58
|
+
async constructParty (hints: KeyHint[]): Promise<HaloParty> {
|
|
59
|
+
const credentialsSigner = CredentialsSigner.createDirectDeviceSigner(this._keyring);
|
|
60
|
+
const feedProvider = this._feedProviderFactory(credentialsSigner.getIdentityKey().publicKey);
|
|
61
|
+
const halo = new HaloParty(
|
|
62
|
+
this._modelFactory,
|
|
63
|
+
this._snapshotStore,
|
|
64
|
+
feedProvider,
|
|
65
|
+
credentialsSigner,
|
|
66
|
+
this._networkManager,
|
|
67
|
+
hints,
|
|
68
|
+
undefined,
|
|
69
|
+
this._options
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
return halo;
|
|
51
73
|
}
|
|
52
74
|
|
|
53
|
-
async createHalo (options: HaloCreationOptions = {}): Promise<
|
|
75
|
+
async createHalo (options: HaloCreationOptions = {}): Promise<HaloParty> {
|
|
54
76
|
// Don't use `identityManager.identityKey`, because that doesn't check for the secretKey.
|
|
55
77
|
const identityKey = this._keyring.findKey(Keyring.signingFilter({ type: KeyType.IDENTITY }));
|
|
56
78
|
assert(identityKey, 'Identity key required.');
|
|
@@ -59,8 +81,10 @@ export class HaloFactory {
|
|
|
59
81
|
await this._keyring.createKeyRecord({ type: KeyType.DEVICE });
|
|
60
82
|
|
|
61
83
|
// 1. Create a feed for the HALO.
|
|
62
|
-
const halo = await this.
|
|
63
|
-
const
|
|
84
|
+
const halo = await this.constructParty([]);
|
|
85
|
+
const feedKey = await halo.getWriteFeedKey();
|
|
86
|
+
const feedKeyPair = this._keyring.getKey(feedKey);
|
|
87
|
+
assert(feedKeyPair);
|
|
64
88
|
|
|
65
89
|
// Connect the pipeline.
|
|
66
90
|
await halo.open();
|
|
@@ -70,8 +94,6 @@ export class HaloFactory {
|
|
|
70
94
|
* B. Device key (the first "member" of the Identity's HALO).
|
|
71
95
|
* C. Feed key (the feed owned by the Device).
|
|
72
96
|
*/
|
|
73
|
-
const feedKeyPair = this._keyring.getKey(feed.key);
|
|
74
|
-
assert(feedKeyPair);
|
|
75
97
|
await halo.processor.writeHaloMessage(createPartyGenesisMessage(this._keyring, identityKey, feedKeyPair.publicKey, deviceKey));
|
|
76
98
|
|
|
77
99
|
/* 3. Make a special self-signed KeyAdmit message which will serve as an "IdentityGenesis" message. This
|
|
@@ -105,15 +127,16 @@ export class HaloFactory {
|
|
|
105
127
|
return halo;
|
|
106
128
|
}
|
|
107
129
|
|
|
108
|
-
async recoverHalo (
|
|
130
|
+
async recoverHalo (seedPhrase: string) {
|
|
109
131
|
const recoveredKeyPair = keyPairFromSeedPhrase(seedPhrase);
|
|
110
132
|
await this._keyring.addKeyRecord({
|
|
111
133
|
publicKey: PublicKey.from(recoveredKeyPair.publicKey),
|
|
112
134
|
secretKey: recoveredKeyPair.secretKey,
|
|
113
135
|
type: KeyType.IDENTITY
|
|
114
136
|
});
|
|
137
|
+
await this._keyring.createKeyRecord({ type: KeyType.DEVICE });
|
|
115
138
|
|
|
116
|
-
const recoverer = new HaloRecoveryInitiator(this._networkManager,
|
|
139
|
+
const recoverer = new HaloRecoveryInitiator(this._networkManager, CredentialsSigner.createDirectDeviceSigner(this._keyring));
|
|
117
140
|
await recoverer.connect();
|
|
118
141
|
|
|
119
142
|
const invitationDescriptor = await recoverer.claim();
|
|
@@ -122,7 +145,7 @@ export class HaloFactory {
|
|
|
122
145
|
}
|
|
123
146
|
|
|
124
147
|
async joinHalo (invitationDescriptor: InvitationDescriptor, secretProvider: SecretProvider) {
|
|
125
|
-
assert(!this._keyring.findKey(Filter.matches({ type: KeyType.
|
|
148
|
+
assert(!this._keyring.findKey(Filter.matches({ type: KeyType.IDENTITY })), 'Identity key must not exist.');
|
|
126
149
|
|
|
127
150
|
return this._joinHalo(invitationDescriptor, secretProvider);
|
|
128
151
|
}
|
|
@@ -131,9 +154,9 @@ export class HaloFactory {
|
|
|
131
154
|
log(`Admitting device with invitation: ${keyToString(invitationDescriptor.invitation)}`);
|
|
132
155
|
assert(invitationDescriptor.identityKey);
|
|
133
156
|
|
|
134
|
-
|
|
157
|
+
let identityKey = this._keyring.findKey(Keyring.signingFilter({ type: KeyType.IDENTITY }));
|
|
135
158
|
if (!identityKey) {
|
|
136
|
-
await this._keyring.addPublicKey({
|
|
159
|
+
identityKey = await this._keyring.addPublicKey({
|
|
137
160
|
type: KeyType.IDENTITY,
|
|
138
161
|
publicKey: invitationDescriptor.identityKey,
|
|
139
162
|
own: true,
|
|
@@ -143,11 +166,51 @@ export class HaloFactory {
|
|
|
143
166
|
assert(identityKey.publicKey.equals(invitationDescriptor.identityKey),
|
|
144
167
|
'Identity key must match invitation');
|
|
145
168
|
}
|
|
169
|
+
assert(identityKey);
|
|
146
170
|
|
|
147
171
|
const deviceKey = this._keyring.findKey(Keyring.signingFilter({ type: KeyType.DEVICE })) ??
|
|
148
172
|
await this._keyring.createKeyRecord({ type: KeyType.DEVICE });
|
|
149
173
|
|
|
150
|
-
const
|
|
174
|
+
const originalInvitation = invitationDescriptor;
|
|
175
|
+
|
|
176
|
+
const credentialsSigner = CredentialsSigner.createDirectDeviceSigner(this._keyring);
|
|
177
|
+
// Claim the offline invitation and convert it into an interactive invitation.
|
|
178
|
+
if (invitationDescriptor.type === InvitationDescriptorType.OFFLINE) {
|
|
179
|
+
const invitationClaimer = new OfflineInvitationClaimer(this._networkManager, invitationDescriptor);
|
|
180
|
+
await invitationClaimer.connect();
|
|
181
|
+
invitationDescriptor = await invitationClaimer.claim();
|
|
182
|
+
log(`Party invitation triggered interactive Greeting at: ${JSON.stringify({ original: originalInvitation.invitation, interactive: invitationDescriptor.invitation })}`);
|
|
183
|
+
await invitationClaimer.destroy();
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const initiator = new GreetingInitiator(
|
|
187
|
+
this._networkManager,
|
|
188
|
+
invitationDescriptor,
|
|
189
|
+
async (partyKey, nonce) => {
|
|
190
|
+
assert(partyKey.equals(identityKey!.publicKey));
|
|
191
|
+
return [createHaloPartyAdmissionMessage(credentialsSigner, nonce)];
|
|
192
|
+
}
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
await initiator.connect();
|
|
196
|
+
const { partyKey, hints } = await initiator.redeemInvitation(secretProvider);
|
|
197
|
+
|
|
198
|
+
/*
|
|
199
|
+
* TODO(telackey): We shouldn't have to add our key here, it should be in the hints, but our hint
|
|
200
|
+
* mechanism is broken by not waiting on the messages to be processed before returning.
|
|
201
|
+
*/
|
|
202
|
+
const halo = await this.constructParty(hints);
|
|
203
|
+
await halo.open();
|
|
204
|
+
|
|
205
|
+
// Write the Feed genesis message.
|
|
206
|
+
await halo.processor.writeHaloMessage(createFeedAdmitMessage(
|
|
207
|
+
credentialsSigner.signer,
|
|
208
|
+
partyKey,
|
|
209
|
+
await halo.getWriteFeedKey(),
|
|
210
|
+
[credentialsSigner.getDeviceKey()]
|
|
211
|
+
));
|
|
212
|
+
await initiator.destroy();
|
|
213
|
+
|
|
151
214
|
await halo.database.createItem({
|
|
152
215
|
model: ObjectModel,
|
|
153
216
|
type: HALO_PARTY_DEVICE_PREFERENCES_TYPE,
|