@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
|
@@ -12,13 +12,13 @@ import { it as test } from 'mocha';
|
|
|
12
12
|
import { latch } from '@dxos/async';
|
|
13
13
|
import {
|
|
14
14
|
createPartyGenesisMessage,
|
|
15
|
+
defaultSecretProvider,
|
|
15
16
|
Keyring, KeyType,
|
|
16
17
|
SecretProvider,
|
|
17
18
|
SecretValidator
|
|
18
19
|
} from '@dxos/credentials';
|
|
19
20
|
import {
|
|
20
|
-
createKeyPair,
|
|
21
|
-
keyPairFromSeedPhrase, PublicKey,
|
|
21
|
+
createKeyPair, PublicKey,
|
|
22
22
|
randomBytes,
|
|
23
23
|
sign,
|
|
24
24
|
SIGNATURE_LENGTH, verify
|
|
@@ -30,18 +30,17 @@ import { ModelFactory } from '@dxos/model-factory';
|
|
|
30
30
|
import { NetworkManager } from '@dxos/network-manager';
|
|
31
31
|
import { ObjectModel } from '@dxos/object-model';
|
|
32
32
|
import { createStorage, StorageType } from '@dxos/random-access-multi-storage';
|
|
33
|
-
import { afterTest } from '@dxos/testutils';
|
|
33
|
+
import { afterTest, testTimeout } from '@dxos/testutils';
|
|
34
34
|
|
|
35
35
|
import { Item } from '../api';
|
|
36
|
-
import {
|
|
37
|
-
import { OfflineInvitationClaimer } from '../invitations';
|
|
38
|
-
import { MetadataStore } from '../
|
|
39
|
-
import { PartyFeedProvider } from '../pipeline';
|
|
36
|
+
import { HaloFactory, Identity, IdentityManager } from '../halo';
|
|
37
|
+
import { defaultInvitationAuthenticator, OfflineInvitationClaimer } from '../invitations';
|
|
38
|
+
import { MetadataStore, PartyFeedProvider } from '../pipeline';
|
|
40
39
|
import { SnapshotStore } from '../snapshots';
|
|
41
40
|
import { messageLogger } from '../testing';
|
|
42
41
|
import { createRamStorage } from '../util';
|
|
42
|
+
import { PARTY_ITEM_TYPE } from './data-party';
|
|
43
43
|
import { PartyFactory } from './party-factory';
|
|
44
|
-
import { PARTY_ITEM_TYPE } from './party-internal';
|
|
45
44
|
import { PartyManager } from './party-manager';
|
|
46
45
|
|
|
47
46
|
const log = debug('dxos:echo:parties:party-manager:test');
|
|
@@ -55,62 +54,53 @@ const log = debug('dxos:echo:parties:party-manager:test');
|
|
|
55
54
|
* @param open - Open the PartyManager
|
|
56
55
|
* @param createIdentity - Create the identity key record.
|
|
57
56
|
*/
|
|
58
|
-
const setup = async (
|
|
57
|
+
const setup = async () => {
|
|
59
58
|
const keyring = new Keyring();
|
|
60
59
|
const metadataStore = new MetadataStore(createRamStorage());
|
|
61
60
|
const feedStore = new FeedStore(createStorage('', StorageType.RAM), { valueEncoding: codec });
|
|
62
61
|
|
|
63
|
-
|
|
64
|
-
if (createIdentity) {
|
|
65
|
-
seedPhrase = generateSeedPhrase();
|
|
66
|
-
const keyPair = keyPairFromSeedPhrase(seedPhrase);
|
|
67
|
-
await keyring.addKeyRecord({
|
|
68
|
-
publicKey: PublicKey.from(keyPair.publicKey),
|
|
69
|
-
secretKey: keyPair.secretKey,
|
|
70
|
-
type: KeyType.IDENTITY
|
|
71
|
-
});
|
|
62
|
+
const identityKey = await keyring.createKeyRecord({ type: KeyType.IDENTITY });
|
|
72
63
|
|
|
73
|
-
|
|
74
|
-
}
|
|
64
|
+
assert(keyring.keys.length === 1);
|
|
75
65
|
|
|
76
66
|
const snapshotStore = new SnapshotStore(createStorage('', StorageType.RAM));
|
|
77
67
|
const modelFactory = new ModelFactory().registerModel(ObjectModel);
|
|
78
68
|
const networkManager = new NetworkManager();
|
|
79
69
|
const feedProviderFactory = (partyKey: PublicKey) => new PartyFeedProvider(metadataStore, keyring, feedStore, partyKey);
|
|
80
|
-
|
|
81
|
-
|
|
70
|
+
|
|
71
|
+
const haloFactory = new HaloFactory(
|
|
82
72
|
networkManager,
|
|
83
73
|
modelFactory,
|
|
84
74
|
snapshotStore,
|
|
85
75
|
feedProviderFactory,
|
|
76
|
+
keyring,
|
|
86
77
|
{
|
|
87
78
|
writeLogger: messageLogger('<<<'),
|
|
88
79
|
readLogger: messageLogger('>>>')
|
|
89
80
|
}
|
|
90
81
|
);
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const identityManager = new IdentityManager(keyring, haloFactory, metadataStore);
|
|
94
|
-
const partyManager = new PartyManager(metadataStore, snapshotStore, () => identityManager.identity, partyFactory);
|
|
95
|
-
afterTest(() => partyManager.close());
|
|
96
|
-
|
|
97
|
-
identityManager.ready.once(() => {
|
|
98
|
-
assert(identityManager.identity.halo?.isOpen);
|
|
99
|
-
const unsub = autoPartyOpener(identityManager.identity.preferences!, partyManager);
|
|
100
|
-
afterTest(unsub);
|
|
82
|
+
const haloParty = await haloFactory.createHalo({
|
|
83
|
+
identityDisplayName: identityKey.publicKey.humanize()
|
|
101
84
|
});
|
|
85
|
+
afterTest(() => haloParty.close());
|
|
86
|
+
const identity = new Identity(keyring, haloParty);
|
|
102
87
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
88
|
+
const partyFactory = new PartyFactory(
|
|
89
|
+
() => identity,
|
|
90
|
+
networkManager,
|
|
91
|
+
modelFactory,
|
|
92
|
+
snapshotStore,
|
|
93
|
+
feedProviderFactory,
|
|
94
|
+
{
|
|
95
|
+
writeLogger: messageLogger('<<<'),
|
|
96
|
+
readLogger: messageLogger('>>>')
|
|
110
97
|
}
|
|
111
|
-
|
|
98
|
+
);
|
|
99
|
+
const partyManager = new PartyManager(metadataStore, snapshotStore, () => identity, partyFactory);
|
|
100
|
+
await partyManager.open();
|
|
101
|
+
afterTest(() => partyManager.close());
|
|
112
102
|
|
|
113
|
-
return { feedStore, partyManager,
|
|
103
|
+
return { feedStore, partyManager, identity };
|
|
114
104
|
};
|
|
115
105
|
|
|
116
106
|
describe('Party manager', () => {
|
|
@@ -120,7 +110,7 @@ describe('Party manager', () => {
|
|
|
120
110
|
});
|
|
121
111
|
|
|
122
112
|
test('Created locally', async () => {
|
|
123
|
-
const { partyManager,
|
|
113
|
+
const { partyManager, identity } = await setup();
|
|
124
114
|
|
|
125
115
|
const [update, setUpdated] = latch();
|
|
126
116
|
const unsubscribe = partyManager.update.on((party) => {
|
|
@@ -134,10 +124,10 @@ describe('Party manager', () => {
|
|
|
134
124
|
expect(party.isOpen).toBeTruthy();
|
|
135
125
|
|
|
136
126
|
// The Party key is an inception key, so its secret should be destroyed immediately after use.
|
|
137
|
-
const partyKey =
|
|
127
|
+
const partyKey = identity.keyring.getKey(party.key);
|
|
138
128
|
expect(partyKey).toBeDefined();
|
|
139
129
|
assert(partyKey);
|
|
140
|
-
expect(
|
|
130
|
+
expect(identity.keyring.hasSecretKey(partyKey)).toBe(false);
|
|
141
131
|
|
|
142
132
|
await update;
|
|
143
133
|
});
|
|
@@ -192,8 +182,20 @@ describe('Party manager', () => {
|
|
|
192
182
|
const snapshotStore = new SnapshotStore(createStorage('', StorageType.RAM));
|
|
193
183
|
const networkManager = new NetworkManager();
|
|
194
184
|
const feedProviderFactory = (partyKey: PublicKey) => new PartyFeedProvider(metadataStore, keyring, feedStore, partyKey);
|
|
195
|
-
const partyFactory
|
|
196
|
-
|
|
185
|
+
const partyFactory = new PartyFactory(
|
|
186
|
+
() => identityManager.identity,
|
|
187
|
+
networkManager,
|
|
188
|
+
modelFactory,
|
|
189
|
+
snapshotStore,
|
|
190
|
+
feedProviderFactory
|
|
191
|
+
);
|
|
192
|
+
const haloFactory: HaloFactory = new HaloFactory(
|
|
193
|
+
networkManager,
|
|
194
|
+
modelFactory,
|
|
195
|
+
snapshotStore,
|
|
196
|
+
feedProviderFactory,
|
|
197
|
+
keyring
|
|
198
|
+
);
|
|
197
199
|
const identityManager = new IdentityManager(keyring, haloFactory, metadataStore);
|
|
198
200
|
const partyManager = new PartyManager(metadataStore, snapshotStore, () => identityManager.identity, partyFactory);
|
|
199
201
|
|
|
@@ -233,6 +235,8 @@ describe('Party manager', () => {
|
|
|
233
235
|
}
|
|
234
236
|
|
|
235
237
|
// Open.
|
|
238
|
+
await identityManager.createHalo();
|
|
239
|
+
afterTest(() => identityManager.close());
|
|
236
240
|
await partyManager.open();
|
|
237
241
|
expect(partyManager.parties).toHaveLength(numParties);
|
|
238
242
|
await partyManager.close();
|
|
@@ -246,7 +250,7 @@ describe('Party manager', () => {
|
|
|
246
250
|
const PIN = Buffer.from('0000');
|
|
247
251
|
const secretProvider: SecretProvider = async () => PIN;
|
|
248
252
|
const secretValidator: SecretValidator = async (invitation, secret) => secret.equals(PIN);
|
|
249
|
-
await partyA.invitationManager.createInvitation({ secretProvider, secretValidator }, { expiration: Date.now() +
|
|
253
|
+
await partyA.invitationManager.createInvitation({ secretProvider, secretValidator }, { expiration: Date.now() + 1000 });
|
|
250
254
|
});
|
|
251
255
|
|
|
252
256
|
test('Create invitation', async () => {
|
|
@@ -278,8 +282,8 @@ describe('Party manager', () => {
|
|
|
278
282
|
});
|
|
279
283
|
|
|
280
284
|
test('Join a party - PIN', async () => {
|
|
281
|
-
const { partyManager: partyManagerA,
|
|
282
|
-
const { partyManager: partyManagerB,
|
|
285
|
+
const { partyManager: partyManagerA, identity: identityA } = await setup();
|
|
286
|
+
const { partyManager: partyManagerB, identity: identityB } = await setup();
|
|
283
287
|
|
|
284
288
|
// Create the Party.
|
|
285
289
|
expect(partyManagerA.parties).toHaveLength(0);
|
|
@@ -339,13 +343,13 @@ describe('Party manager', () => {
|
|
|
339
343
|
const members = party.queryMembers().value;
|
|
340
344
|
expect(members.length).toBe(2);
|
|
341
345
|
for (const member of members) {
|
|
342
|
-
if (
|
|
343
|
-
expect(member.displayName).toEqual(
|
|
344
|
-
expect(member.displayName).toEqual(
|
|
346
|
+
if (identityA.identityKey!.publicKey.equals(member.publicKey)) {
|
|
347
|
+
expect(member.displayName).toEqual(identityA.identityKey!.publicKey.humanize());
|
|
348
|
+
expect(member.displayName).toEqual(identityA.displayName);
|
|
345
349
|
}
|
|
346
|
-
if (
|
|
347
|
-
expect(member.displayName).toEqual(
|
|
348
|
-
expect(member.displayName).toEqual(
|
|
350
|
+
if (identityB.identityKey!.publicKey.equals(member.publicKey)) {
|
|
351
|
+
expect(member.displayName).toEqual(identityB.identityKey!.publicKey.humanize());
|
|
352
|
+
expect(member.displayName).toEqual(identityB.displayName);
|
|
349
353
|
}
|
|
350
354
|
}
|
|
351
355
|
}
|
|
@@ -354,8 +358,8 @@ describe('Party manager', () => {
|
|
|
354
358
|
});
|
|
355
359
|
|
|
356
360
|
test('Join a party - signature', async () => {
|
|
357
|
-
const { partyManager: partyManagerA,
|
|
358
|
-
const { partyManager: partyManagerB,
|
|
361
|
+
const { partyManager: partyManagerA, identity: identityA } = await setup();
|
|
362
|
+
const { partyManager: partyManagerB, identity: identityB } = await setup();
|
|
359
363
|
|
|
360
364
|
// This would typically be a keypair associated with BotFactory.
|
|
361
365
|
const keyPair = createKeyPair();
|
|
@@ -420,21 +424,19 @@ describe('Party manager', () => {
|
|
|
420
424
|
const members = party.queryMembers().value;
|
|
421
425
|
expect(members.length).toBe(2);
|
|
422
426
|
for (const member of members) {
|
|
423
|
-
if (
|
|
424
|
-
expect(member.displayName).toEqual(
|
|
427
|
+
if (identityA.identityKey!.publicKey.equals(member.publicKey)) {
|
|
428
|
+
expect(member.displayName).toEqual(identityA.identityKey!.publicKey.humanize());
|
|
425
429
|
}
|
|
426
|
-
if (
|
|
427
|
-
expect(member.displayName).toEqual(
|
|
430
|
+
if (identityB.identityKey!.publicKey.equals(member.publicKey)) {
|
|
431
|
+
expect(member.displayName).toEqual(identityB.identityKey!.publicKey.humanize());
|
|
428
432
|
}
|
|
429
433
|
}
|
|
430
434
|
}
|
|
431
435
|
});
|
|
432
436
|
|
|
433
437
|
test('Join a party - Offline', async () => {
|
|
434
|
-
const { partyManager: partyManagerA,
|
|
435
|
-
const { partyManager: partyManagerB,
|
|
436
|
-
assert(identityManagerA.identity.identityKey);
|
|
437
|
-
assert(identityManagerB.identity.identityKey);
|
|
438
|
+
const { partyManager: partyManagerA, identity: identityA } = await setup();
|
|
439
|
+
const { partyManager: partyManagerB, identity: identityB } = await setup();
|
|
438
440
|
|
|
439
441
|
// Create the Party.
|
|
440
442
|
expect(partyManagerA.parties).toHaveLength(0);
|
|
@@ -443,12 +445,12 @@ describe('Party manager', () => {
|
|
|
443
445
|
log(`Created ${partyA.key.toHex()}`);
|
|
444
446
|
|
|
445
447
|
const invitationDescriptor = await partyA.invitationManager
|
|
446
|
-
.createOfflineInvitation(
|
|
448
|
+
.createOfflineInvitation(identityB.identityKey!.publicKey);
|
|
447
449
|
|
|
448
450
|
// Redeem the invitation on B.
|
|
449
451
|
expect(partyManagerB.parties).toHaveLength(0);
|
|
450
452
|
const partyB = await partyManagerB.joinParty(invitationDescriptor,
|
|
451
|
-
OfflineInvitationClaimer.createSecretProvider(
|
|
453
|
+
OfflineInvitationClaimer.createSecretProvider(identityB));
|
|
452
454
|
expect(partyB).toBeDefined();
|
|
453
455
|
log(`Joined ${partyB.key.toHex()}`);
|
|
454
456
|
|
|
@@ -479,18 +481,42 @@ describe('Party manager', () => {
|
|
|
479
481
|
const members = party.queryMembers().value;
|
|
480
482
|
expect(members.length).toBe(2);
|
|
481
483
|
for (const member of members) {
|
|
482
|
-
if (
|
|
483
|
-
expect(member.displayName).toEqual(
|
|
484
|
-
expect(member.displayName).toEqual(
|
|
484
|
+
if (identityA.identityKey!.publicKey.equals(member.publicKey)) {
|
|
485
|
+
expect(member.displayName).toEqual(identityA.identityKey!.publicKey.humanize());
|
|
486
|
+
expect(member.displayName).toEqual(identityA.displayName);
|
|
485
487
|
}
|
|
486
|
-
if (
|
|
487
|
-
expect(member.displayName).toEqual(
|
|
488
|
-
expect(member.displayName).toEqual(
|
|
488
|
+
if (identityB.identityKey!.publicKey.equals(member.publicKey)) {
|
|
489
|
+
expect(member.displayName).toEqual(identityB.identityKey!.publicKey.humanize());
|
|
490
|
+
expect(member.displayName).toEqual(identityB.displayName);
|
|
489
491
|
}
|
|
490
492
|
}
|
|
491
493
|
}
|
|
492
494
|
}).timeout(10_000);
|
|
493
495
|
|
|
496
|
+
test('3 peers in a party', async () => {
|
|
497
|
+
const { partyManager: partyManagerA } = await setup();
|
|
498
|
+
const { partyManager: partyManagerB } = await setup();
|
|
499
|
+
const { partyManager: partyManagerC } = await setup();
|
|
500
|
+
|
|
501
|
+
const partyA = await partyManagerA.createParty();
|
|
502
|
+
|
|
503
|
+
const invitationA = await partyA.invitationManager.createInvitation(defaultInvitationAuthenticator);
|
|
504
|
+
const partyB = await partyManagerB.joinParty(invitationA, defaultSecretProvider);
|
|
505
|
+
|
|
506
|
+
const invitationB = await partyB.invitationManager.createInvitation(defaultInvitationAuthenticator);
|
|
507
|
+
const partyC = await partyManagerC.joinParty(invitationB, defaultSecretProvider);
|
|
508
|
+
|
|
509
|
+
await partyA.database.createItem({ type: 'test:item-a' });
|
|
510
|
+
await partyB.database.createItem({ type: 'test:item-b' });
|
|
511
|
+
await partyC.database.createItem({ type: 'test:item-c' });
|
|
512
|
+
|
|
513
|
+
for (const party of [partyA, partyB, partyC]) {
|
|
514
|
+
await testTimeout(party.database.waitForItem({ type: 'test:item-a' }));
|
|
515
|
+
await testTimeout(party.database.waitForItem({ type: 'test:item-b' }));
|
|
516
|
+
await testTimeout(party.database.waitForItem({ type: 'test:item-c' }));
|
|
517
|
+
}
|
|
518
|
+
});
|
|
519
|
+
|
|
494
520
|
test('Clone party', async () => {
|
|
495
521
|
const { partyManager } = await setup();
|
|
496
522
|
|
|
@@ -15,10 +15,10 @@ import { ComplexMap, boolGuard } from '@dxos/util';
|
|
|
15
15
|
|
|
16
16
|
import { IdentityProvider } from '../halo';
|
|
17
17
|
import { InvitationDescriptor } from '../invitations';
|
|
18
|
-
import { MetadataStore } from '../
|
|
18
|
+
import { MetadataStore } from '../pipeline';
|
|
19
19
|
import { SnapshotStore } from '../snapshots';
|
|
20
|
+
import { DataParty, PARTY_ITEM_TYPE, PARTY_TITLE_PROPERTY } from './data-party';
|
|
20
21
|
import { PartyFactory } from './party-factory';
|
|
21
|
-
import { PartyInternal, PARTY_ITEM_TYPE, PARTY_TITLE_PROPERTY } from './party-internal';
|
|
22
22
|
|
|
23
23
|
export const CONTACT_DEBOUNCE_INTERVAL = 500;
|
|
24
24
|
|
|
@@ -33,14 +33,14 @@ export interface OpenProgress {
|
|
|
33
33
|
/**
|
|
34
34
|
* Top-level class manages the complete life-cycle of parties.
|
|
35
35
|
*
|
|
36
|
-
* `
|
|
36
|
+
* `ECHO` => `PartyManager` => `DataParty` => `PartyCore`
|
|
37
37
|
*/
|
|
38
38
|
export class PartyManager {
|
|
39
39
|
// External event listener.
|
|
40
|
-
readonly update = new Event<
|
|
40
|
+
readonly update = new Event<DataParty>();
|
|
41
41
|
|
|
42
42
|
// Map of parties by party key.
|
|
43
|
-
private readonly _parties = new ComplexMap<PublicKey,
|
|
43
|
+
private readonly _parties = new ComplexMap<PublicKey, DataParty>(key => key.toHex());
|
|
44
44
|
|
|
45
45
|
// Unsubscribe handlers.
|
|
46
46
|
// TODO(burdon): Never used.
|
|
@@ -59,7 +59,7 @@ export class PartyManager {
|
|
|
59
59
|
return this._open;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
get parties ():
|
|
62
|
+
get parties (): DataParty[] {
|
|
63
63
|
return Array.from(this._parties.values());
|
|
64
64
|
}
|
|
65
65
|
|
|
@@ -77,7 +77,7 @@ export class PartyManager {
|
|
|
77
77
|
const identity = this._identityProvider();
|
|
78
78
|
|
|
79
79
|
// TODO(telackey): Does it make any sense to load other parties if we don't have an HALO?
|
|
80
|
-
if (identity
|
|
80
|
+
if (identity?.identityKey) {
|
|
81
81
|
partyKeys = partyKeys.filter(partyKey => !partyKey.equals(identity.identityKey!.publicKey));
|
|
82
82
|
}
|
|
83
83
|
|
|
@@ -97,7 +97,7 @@ export class PartyManager {
|
|
|
97
97
|
? await this._partyFactory.constructPartyFromSnapshot(snapshot)
|
|
98
98
|
: await this._partyFactory.constructParty(partyKey);
|
|
99
99
|
|
|
100
|
-
const isActive = identity
|
|
100
|
+
const isActive = identity?.preferences?.isPartyActive(partyKey) ?? true;
|
|
101
101
|
if (isActive) {
|
|
102
102
|
await party.open();
|
|
103
103
|
// TODO(marik-d): Might not be required if separately snapshot this item.
|
|
@@ -141,7 +141,7 @@ export class PartyManager {
|
|
|
141
141
|
* Creates a new party, writing its genesis block to the stream.
|
|
142
142
|
*/
|
|
143
143
|
@synchronized
|
|
144
|
-
async createParty (): Promise<
|
|
144
|
+
async createParty (): Promise<DataParty> {
|
|
145
145
|
assert(this._open, 'PartyManager is not open.');
|
|
146
146
|
|
|
147
147
|
const party = await this._partyFactory.createParty();
|
|
@@ -224,7 +224,7 @@ export class PartyManager {
|
|
|
224
224
|
return party;
|
|
225
225
|
}
|
|
226
226
|
|
|
227
|
-
private _setParty (party:
|
|
227
|
+
private _setParty (party: DataParty) {
|
|
228
228
|
const updateContact = async () => {
|
|
229
229
|
try {
|
|
230
230
|
await this._updateContactList(party);
|
|
@@ -258,7 +258,7 @@ export class PartyManager {
|
|
|
258
258
|
}
|
|
259
259
|
|
|
260
260
|
// TODO(burdon): Refactor.
|
|
261
|
-
private async _updatePartyTitle (party:
|
|
261
|
+
private async _updatePartyTitle (party: DataParty) {
|
|
262
262
|
if (!this._open) {
|
|
263
263
|
return;
|
|
264
264
|
}
|
|
@@ -266,14 +266,14 @@ export class PartyManager {
|
|
|
266
266
|
const identity = this._identityProvider();
|
|
267
267
|
const item = await party.getPropertiesItem();
|
|
268
268
|
const currentTitle = item.model.get(PARTY_TITLE_PROPERTY);
|
|
269
|
-
const storedTitle = identity
|
|
269
|
+
const storedTitle = identity?.preferences?.getGlobalPartyPreference(party.key, PARTY_TITLE_PROPERTY);
|
|
270
270
|
if (storedTitle !== currentTitle) {
|
|
271
|
-
await identity
|
|
271
|
+
await identity?.preferences?.setGlobalPartyPreference(party, PARTY_TITLE_PROPERTY, currentTitle);
|
|
272
272
|
}
|
|
273
273
|
}
|
|
274
274
|
|
|
275
275
|
// TODO(burdon): Reconcile with `Halo.ContactManager`.
|
|
276
|
-
private async _updateContactList (party:
|
|
276
|
+
private async _updateContactList (party: DataParty) {
|
|
277
277
|
// Prevent any updates after we closed ECHO.
|
|
278
278
|
// This will get re-run next time echo is loaded so we don't loose any data.
|
|
279
279
|
if (!this._open) {
|
|
@@ -282,7 +282,7 @@ export class PartyManager {
|
|
|
282
282
|
|
|
283
283
|
const identity = this._identityProvider();
|
|
284
284
|
|
|
285
|
-
const contactListItem = identity
|
|
285
|
+
const contactListItem = identity?.contacts?.getContactListItem();
|
|
286
286
|
if (!contactListItem) {
|
|
287
287
|
return;
|
|
288
288
|
}
|
|
@@ -314,11 +314,11 @@ export class PartyManager {
|
|
|
314
314
|
}
|
|
315
315
|
|
|
316
316
|
@timed(5_000)
|
|
317
|
-
private async _recordPartyJoining (party:
|
|
317
|
+
private async _recordPartyJoining (party: DataParty) {
|
|
318
318
|
const identity = this._identityProvider();
|
|
319
319
|
|
|
320
320
|
// TODO(marik-d): Extract HALO functionality from this class.
|
|
321
|
-
if (!identity
|
|
321
|
+
if (!identity?.preferences) {
|
|
322
322
|
return;
|
|
323
323
|
}
|
|
324
324
|
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
import assert from 'assert';
|
|
6
6
|
|
|
7
|
-
import { PARTY_TITLE_PROPERTY,
|
|
8
|
-
import { Preferences } from '
|
|
7
|
+
import { PARTY_TITLE_PROPERTY, DataParty } from '.';
|
|
8
|
+
import { Preferences } from '../halo/preferences';
|
|
9
9
|
|
|
10
10
|
export interface ActivationOptions {
|
|
11
11
|
global?: boolean;
|
|
@@ -21,7 +21,7 @@ export interface ActivationOptions {
|
|
|
21
21
|
export class PartyPreferences {
|
|
22
22
|
constructor (
|
|
23
23
|
private readonly _preferences: Preferences,
|
|
24
|
-
private readonly _party:
|
|
24
|
+
private readonly _party: DataParty
|
|
25
25
|
) {
|
|
26
26
|
assert(this._party);
|
|
27
27
|
}
|
package/src/pipeline/index.ts
CHANGED
|
@@ -5,5 +5,7 @@
|
|
|
5
5
|
export * from './message-selector';
|
|
6
6
|
export * from './party-feed-provider';
|
|
7
7
|
export * from './party-processor';
|
|
8
|
-
export * from '
|
|
8
|
+
export * from '../protocol/party-protocol-factory';
|
|
9
9
|
export * from './pipeline';
|
|
10
|
+
export * from './party-core';
|
|
11
|
+
export * from './metadata-store';
|
|
File without changes
|
|
File without changes
|
|
@@ -16,8 +16,7 @@ import { ObjectModel } from '@dxos/object-model';
|
|
|
16
16
|
import { createStorage, StorageType } from '@dxos/random-access-multi-storage';
|
|
17
17
|
import { afterTest } from '@dxos/testutils';
|
|
18
18
|
|
|
19
|
-
import { MetadataStore } from '../
|
|
20
|
-
import { PartyFeedProvider, ReplicatorProtocolPluginFactory } from '../pipeline';
|
|
19
|
+
import { MetadataStore, PartyFeedProvider, ReplicatorProtocolPluginFactory } from '../pipeline';
|
|
21
20
|
import { SnapshotStore } from '../snapshots';
|
|
22
21
|
import { createRamStorage } from '../util';
|
|
23
22
|
import { PartyCore } from './party-core';
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import assert from 'assert';
|
|
6
6
|
|
|
7
7
|
import { synchronized } from '@dxos/async';
|
|
8
|
-
import { KeyHint } from '@dxos/credentials';
|
|
8
|
+
import { KeyHint, KeyType } from '@dxos/credentials';
|
|
9
9
|
import { PublicKey } from '@dxos/crypto';
|
|
10
10
|
import { timed } from '@dxos/debug';
|
|
11
11
|
import { createFeedWriter, DatabaseSnapshot, PartyKey, PartySnapshot, Timeframe } from '@dxos/echo-protocol';
|
|
@@ -58,7 +58,7 @@ export class PartyCore {
|
|
|
58
58
|
private readonly _memberKey: PublicKey,
|
|
59
59
|
private readonly _initialTimeframe?: Timeframe,
|
|
60
60
|
private readonly _options: PartyOptions = {}
|
|
61
|
-
) {}
|
|
61
|
+
) { }
|
|
62
62
|
|
|
63
63
|
get key (): PartyKey {
|
|
64
64
|
return this._partyKey;
|
|
@@ -111,14 +111,23 @@ export class PartyCore {
|
|
|
111
111
|
|
|
112
112
|
this._timeframeClock = new TimeframeClock(this._initialTimeframe);
|
|
113
113
|
|
|
114
|
+
// Open all feeds known from metadata and open or create a writable feed to the party.
|
|
115
|
+
await this._feedProvider.openKnownFeeds();
|
|
116
|
+
const writableFeed = await this._feedProvider.createOrOpenWritableFeed();
|
|
117
|
+
|
|
114
118
|
if (!this._partyProcessor) {
|
|
115
119
|
this._partyProcessor = new PartyProcessor(this._partyKey);
|
|
116
120
|
}
|
|
121
|
+
|
|
117
122
|
// Automatically open new admitted feeds.
|
|
118
123
|
this._subscriptions.push(this._partyProcessor.feedAdded.on(feed => {
|
|
119
124
|
void this._feedProvider.createOrOpenReadOnlyFeed(feed);
|
|
120
125
|
}));
|
|
121
126
|
|
|
127
|
+
// Hint at our own writable feed.
|
|
128
|
+
// TODO(dmaretskyi): Does not seem like it should be required, but without it replication between devices (B -> A) breaks.
|
|
129
|
+
await this._partyProcessor.takeHints([{ type: KeyType.FEED, publicKey: writableFeed.key }]);
|
|
130
|
+
|
|
122
131
|
if (keyHints.length > 0) {
|
|
123
132
|
await this._partyProcessor.takeHints(keyHints);
|
|
124
133
|
}
|
|
@@ -127,17 +136,13 @@ export class PartyCore {
|
|
|
127
136
|
// Pipeline
|
|
128
137
|
//
|
|
129
138
|
|
|
130
|
-
await this._feedProvider.openKnownFeeds();
|
|
131
139
|
const iterator = await this._feedProvider.createIterator(
|
|
132
140
|
createMessageSelector(this._partyProcessor, this._timeframeClock),
|
|
133
141
|
this._initialTimeframe
|
|
134
142
|
);
|
|
135
143
|
|
|
136
|
-
const { feed } = await this._feedProvider.createOrOpenWritableFeed();
|
|
137
|
-
const feedWriteStream = createFeedWriter(feed);
|
|
138
|
-
|
|
139
144
|
this._pipeline = new Pipeline(
|
|
140
|
-
this._partyProcessor, iterator, this._timeframeClock,
|
|
145
|
+
this._partyProcessor, iterator, this._timeframeClock, createFeedWriter(writableFeed.feed), this._options);
|
|
141
146
|
|
|
142
147
|
// TODO(burdon): Support read-only parties.
|
|
143
148
|
const [readStream, writeStream] = await this._pipeline.open();
|
|
@@ -5,16 +5,17 @@
|
|
|
5
5
|
import assert from 'assert';
|
|
6
6
|
import debug from 'debug';
|
|
7
7
|
|
|
8
|
-
import { Event } from '@dxos/async';
|
|
8
|
+
import { Event, synchronized } from '@dxos/async';
|
|
9
9
|
import { Keyring, KeyType } from '@dxos/credentials';
|
|
10
10
|
import { PublicKey } from '@dxos/crypto';
|
|
11
11
|
import { FeedStoreIterator, MessageSelector, Timeframe } from '@dxos/echo-protocol';
|
|
12
12
|
import { FeedDescriptor, FeedStore } from '@dxos/feed-store';
|
|
13
13
|
import { ComplexMap } from '@dxos/util';
|
|
14
14
|
|
|
15
|
-
import { MetadataStore } from '
|
|
15
|
+
import { MetadataStore } from './metadata-store';
|
|
16
16
|
|
|
17
17
|
const STALL_TIMEOUT = 1000;
|
|
18
|
+
const log = debug('dxos:echo-db:party-feed-provider');
|
|
18
19
|
const warn = debug('dxos:echo-db:party-feed-provider:warn');
|
|
19
20
|
|
|
20
21
|
export class PartyFeedProvider {
|
|
@@ -32,6 +33,20 @@ export class PartyFeedProvider {
|
|
|
32
33
|
return Array.from(this._feeds.values());
|
|
33
34
|
}
|
|
34
35
|
|
|
36
|
+
@synchronized
|
|
37
|
+
async openKnownFeeds () {
|
|
38
|
+
for (const feedKey of this._metadataStore.getParty(this._partyKey)?.feedKeys ?? []) {
|
|
39
|
+
if (!this._feeds.has(feedKey)) {
|
|
40
|
+
const fullKey = this._keyring.getFullKey(feedKey);
|
|
41
|
+
const feed = fullKey?.secretKey
|
|
42
|
+
? await this._feedStore.openReadWriteFeed(fullKey.publicKey, fullKey.secretKey)
|
|
43
|
+
: await this._feedStore.openReadOnlyFeed(feedKey);
|
|
44
|
+
this._trackFeed(feed);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@synchronized
|
|
35
50
|
async createOrOpenWritableFeed () {
|
|
36
51
|
const partyMetadata = this._metadataStore.getParty(this._partyKey);
|
|
37
52
|
if (!partyMetadata?.dataFeedKey) {
|
|
@@ -48,24 +63,11 @@ export class PartyFeedProvider {
|
|
|
48
63
|
}
|
|
49
64
|
|
|
50
65
|
const feed = await this._feedStore.openReadWriteFeed(fullKey.publicKey, fullKey.secretKey);
|
|
51
|
-
this.
|
|
52
|
-
this.feedOpened.emit(feed);
|
|
66
|
+
this._trackFeed(feed);
|
|
53
67
|
return feed;
|
|
54
68
|
}
|
|
55
69
|
|
|
56
|
-
|
|
57
|
-
for (const feedKey of this._metadataStore.getParty(this._partyKey)?.feedKeys ?? []) {
|
|
58
|
-
if (!this._feeds.has(feedKey)) {
|
|
59
|
-
const fullKey = this._keyring.getFullKey(feedKey);
|
|
60
|
-
const feed = fullKey?.secretKey
|
|
61
|
-
? await this._feedStore.openReadWriteFeed(fullKey.publicKey, fullKey.secretKey)
|
|
62
|
-
: await this._feedStore.openReadOnlyFeed(feedKey);
|
|
63
|
-
this._feeds.set(feedKey, feed);
|
|
64
|
-
this.feedOpened.emit(feed);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
70
|
+
@synchronized
|
|
69
71
|
async createOrOpenReadOnlyFeed (feedKey: PublicKey): Promise<FeedDescriptor> {
|
|
70
72
|
if (this._feeds.has(feedKey)) {
|
|
71
73
|
return this._feeds.get(feedKey)!;
|
|
@@ -76,19 +78,28 @@ export class PartyFeedProvider {
|
|
|
76
78
|
await this._keyring.addPublicKey({ type: KeyType.FEED, publicKey: feedKey });
|
|
77
79
|
}
|
|
78
80
|
const feed = await this._feedStore.openReadOnlyFeed(feedKey);
|
|
79
|
-
this.
|
|
80
|
-
this.feedOpened.emit(feed);
|
|
81
|
+
this._trackFeed(feed);
|
|
81
82
|
return feed;
|
|
82
83
|
}
|
|
83
84
|
|
|
85
|
+
private _trackFeed (feed: FeedDescriptor) {
|
|
86
|
+
assert(!this._feeds.has(feed.key));
|
|
87
|
+
this._feeds.set(feed.key, feed);
|
|
88
|
+
this.feedOpened.emit(feed);
|
|
89
|
+
|
|
90
|
+
log(`Party feed set changed: ${JSON.stringify({
|
|
91
|
+
party: this._partyKey,
|
|
92
|
+
feeds: Array.from(this._feeds.values()).map(feed => feed.key)
|
|
93
|
+
})}`);
|
|
94
|
+
}
|
|
95
|
+
|
|
84
96
|
private async _createReadWriteFeed () {
|
|
85
97
|
const feedKey = await this._keyring.createKeyRecord({ type: KeyType.FEED });
|
|
86
98
|
const fullKey = this._keyring.getFullKey(feedKey.publicKey);
|
|
87
99
|
assert(fullKey && fullKey.secretKey);
|
|
88
100
|
await this._metadataStore.setDataFeed(this._partyKey, fullKey.publicKey);
|
|
89
101
|
const feed = await this._feedStore.openReadWriteFeed(fullKey.publicKey, fullKey.secretKey);
|
|
90
|
-
this.
|
|
91
|
-
this.feedOpened.emit(feed);
|
|
102
|
+
this._trackFeed(feed);
|
|
92
103
|
return feed;
|
|
93
104
|
}
|
|
94
105
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2022 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { Authenticator, AuthPlugin } from '@dxos/credentials';
|
|
6
|
+
import { PublicKey } from '@dxos/crypto';
|
|
7
|
+
import { Replicator } from '@dxos/protocol-plugin-replicator';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Creates authenticator network-protocol plugin that guards access to the replicator.
|
|
11
|
+
*/
|
|
12
|
+
export function createAuthPlugin (authenticator: Authenticator, peerId: PublicKey) {
|
|
13
|
+
return new AuthPlugin(peerId.asBuffer(), authenticator, [Replicator.extension]);
|
|
14
|
+
}
|