@dxos/client 2.24.1-dev.79448ad7 → 2.25.1-dev.3e7251f9

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 (79) hide show
  1. package/dist/src/api/echo-proxy.d.ts +7 -7
  2. package/dist/src/api/echo-proxy.d.ts.map +1 -1
  3. package/dist/src/api/echo-proxy.js +10 -8
  4. package/dist/src/api/echo-proxy.js.map +1 -1
  5. package/dist/src/api/halo-proxy.d.ts +4 -1
  6. package/dist/src/api/halo-proxy.d.ts.map +1 -1
  7. package/dist/src/api/halo-proxy.js +18 -9
  8. package/dist/src/api/halo-proxy.js.map +1 -1
  9. package/dist/src/api/party-proxy.d.ts +6 -6
  10. package/dist/src/api/party-proxy.d.ts.map +1 -1
  11. package/dist/src/api/party-proxy.js +18 -9
  12. package/dist/src/api/party-proxy.js.map +1 -1
  13. package/dist/src/client/client-services.test.js +5 -5
  14. package/dist/src/client/client.d.ts +1 -1
  15. package/dist/src/client/client.js +3 -3
  16. package/dist/src/client/client.js.map +1 -1
  17. package/dist/src/client/client.test.js +2 -2
  18. package/dist/src/client/client.test.js.map +1 -1
  19. package/dist/src/client/service-host/services/halo.d.ts +14 -0
  20. package/dist/src/client/service-host/services/halo.d.ts.map +1 -0
  21. package/dist/src/client/service-host/services/halo.js +73 -0
  22. package/dist/src/client/service-host/services/halo.js.map +1 -0
  23. package/dist/src/client/service-host/services/party.d.ts +10 -10
  24. package/dist/src/client/service-host/services/party.d.ts.map +1 -1
  25. package/dist/src/client/service-host/services/party.js +13 -13
  26. package/dist/src/client/service-host/services/party.js.map +1 -1
  27. package/dist/src/client/service-host/services/profile.d.ts +7 -8
  28. package/dist/src/client/service-host/services/profile.d.ts.map +1 -1
  29. package/dist/src/client/service-host/services/profile.js +6 -25
  30. package/dist/src/client/service-host/services/profile.js.map +1 -1
  31. package/dist/src/client/service-host/services/services.d.ts.map +1 -1
  32. package/dist/src/client/service-host/services/services.js +4 -2
  33. package/dist/src/client/service-host/services/services.js.map +1 -1
  34. package/dist/src/client/service-host/services/system.js +2 -2
  35. package/dist/src/devtools/devtools-host.js +19 -19
  36. package/dist/src/devtools/items.js +2 -2
  37. package/dist/src/devtools/items.js.map +1 -1
  38. package/dist/src/index.d.ts +1 -0
  39. package/dist/src/index.d.ts.map +1 -1
  40. package/dist/src/index.js +12 -1
  41. package/dist/src/index.js.map +1 -1
  42. package/dist/src/interfaces/client-service-provider.d.ts +2 -1
  43. package/dist/src/interfaces/client-service-provider.d.ts.map +1 -1
  44. package/dist/src/interfaces/client-service-provider.js +1 -0
  45. package/dist/src/interfaces/client-service-provider.js.map +1 -1
  46. package/dist/src/proto/gen/dxos/client.d.ts +52 -34
  47. package/dist/src/proto/gen/dxos/client.d.ts.map +1 -1
  48. package/dist/src/proto/gen/dxos/client.js.map +1 -1
  49. package/dist/src/proto/gen/dxos/devtools.d.ts +21 -21
  50. package/dist/src/proto/gen/dxos/echo/service.d.ts +3 -3
  51. package/dist/src/proto/gen/google/protobuf.d.ts +2 -2
  52. package/dist/src/proto/gen/google/protobuf.d.ts.map +1 -1
  53. package/dist/src/proto/gen/google/protobuf.js.map +1 -1
  54. package/dist/src/proto/gen/index.d.ts +4 -0
  55. package/dist/src/proto/gen/index.d.ts.map +1 -1
  56. package/dist/src/proto/gen/index.js +1 -1
  57. package/dist/src/proto/gen/index.js.map +1 -1
  58. package/dist/tsconfig.tsbuildinfo +1 -1
  59. package/package.json +22 -19
  60. package/src/api/echo-proxy.ts +20 -16
  61. package/src/api/halo-proxy.ts +24 -10
  62. package/src/api/party-proxy.ts +21 -11
  63. package/src/client/client-services.test.ts +5 -5
  64. package/src/client/client.test.ts +2 -2
  65. package/src/client/client.ts +3 -3
  66. package/src/client/service-host/services/halo.ts +80 -0
  67. package/src/client/service-host/services/party.ts +15 -15
  68. package/src/client/service-host/services/profile.ts +7 -38
  69. package/src/client/service-host/services/services.ts +4 -2
  70. package/src/client/service-host/services/system.ts +2 -2
  71. package/src/devtools/devtools-host.ts +19 -19
  72. package/src/devtools/items.ts +2 -2
  73. package/src/index.ts +15 -0
  74. package/src/interfaces/client-service-provider.ts +3 -1
  75. package/src/proto/gen/dxos/client.ts +51 -34
  76. package/src/proto/gen/dxos/devtools.ts +21 -21
  77. package/src/proto/gen/dxos/echo/service.ts +3 -3
  78. package/src/proto/gen/google/protobuf.ts +2 -2
  79. package/src/proto/gen/index.ts +5 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/client",
3
- "version": "2.24.1-dev.79448ad7",
3
+ "version": "2.25.1-dev.3e7251f9",
4
4
  "license": "AGPL-3.0",
5
5
  "author": "DXOS.org",
6
6
  "main": "dist/src/index.js",
@@ -10,21 +10,24 @@
10
10
  "src"
11
11
  ],
12
12
  "dependencies": {
13
- "@dxos/async": "2.24.1-dev.79448ad7",
14
- "@dxos/codec-protobuf": "2.24.1-dev.79448ad7",
15
- "@dxos/config": "2.24.1-dev.79448ad7",
16
- "@dxos/credentials": "2.24.1-dev.79448ad7",
17
- "@dxos/crypto": "2.24.1-dev.79448ad7",
18
- "@dxos/debug": "2.24.1-dev.79448ad7",
19
- "@dxos/echo-db": "2.24.1-dev.79448ad7",
20
- "@dxos/echo-protocol": "2.24.1-dev.79448ad7",
21
- "@dxos/feed-store": "2.24.1-dev.79448ad7",
22
- "@dxos/model-factory": "2.24.1-dev.79448ad7",
23
- "@dxos/network-manager": "2.24.1-dev.79448ad7",
24
- "@dxos/object-model": "2.24.1-dev.79448ad7",
25
- "@dxos/proto": "2.24.1-dev.79448ad7",
26
- "@dxos/rpc": "2.24.1-dev.79448ad7",
27
- "@dxos/util": "2.24.1-dev.79448ad7",
13
+ "@dxos/async": "2.25.1-dev.3e7251f9",
14
+ "@dxos/codec-protobuf": "2.25.1-dev.3e7251f9",
15
+ "@dxos/config": "2.25.1-dev.3e7251f9",
16
+ "@dxos/credentials": "2.25.1-dev.3e7251f9",
17
+ "@dxos/crypto": "2.25.1-dev.3e7251f9",
18
+ "@dxos/debug": "2.25.1-dev.3e7251f9",
19
+ "@dxos/echo-db": "2.25.1-dev.3e7251f9",
20
+ "@dxos/echo-protocol": "2.25.1-dev.3e7251f9",
21
+ "@dxos/feed-store": "2.25.1-dev.3e7251f9",
22
+ "@dxos/model-factory": "2.25.1-dev.3e7251f9",
23
+ "@dxos/network-manager": "2.25.1-dev.3e7251f9",
24
+ "@dxos/object-model": "2.25.1-dev.3e7251f9",
25
+ "@dxos/proto": "2.25.1-dev.3e7251f9",
26
+ "@dxos/rpc": "2.25.1-dev.3e7251f9",
27
+ "@dxos/util": "2.25.1-dev.3e7251f9",
28
+ "@polkadot/keyring": "6.11.1",
29
+ "@polkadot/util": "6.11.1",
30
+ "@polkadot/util-crypto": "6.11.1",
28
31
  "@wirelineio/registry-client": "~1.1.0-beta.3",
29
32
  "abstract-leveldown": "~7.0.0",
30
33
  "assert": "^2.0.0",
@@ -38,9 +41,9 @@
38
41
  "uuid": "^8.3.2"
39
42
  },
40
43
  "devDependencies": {
41
- "@dxos/random-access-multi-storage": "2.24.1-dev.79448ad7",
42
- "@dxos/testutils": "2.24.0",
43
- "@dxos/toolchain-node-library": "2.24.0",
44
+ "@dxos/random-access-multi-storage": "2.25.1-dev.3e7251f9",
45
+ "@dxos/testutils": "2.25.0",
46
+ "@dxos/toolchain-node-library": "2.25.0",
44
47
  "@types/debug": "^4.1.7",
45
48
  "@types/expect": "~24.3.0",
46
49
  "@types/jest": "^26.0.7",
@@ -16,20 +16,20 @@ import { ComplexMap, SubscriptionGroup } from '@dxos/util';
16
16
  import { ClientServiceHost } from '../client/service-host';
17
17
  import { ClientServiceProvider } from '../interfaces';
18
18
  import { Invitation, InvitationProxy } from './invitations';
19
- import { PartyProxy } from './party-proxy';
19
+ import { Party } from './party-proxy';
20
20
 
21
- export class PartyInvitation extends Invitation<PartyProxy> {
21
+ export class PartyInvitation extends Invitation<Party> {
22
22
  /**
23
23
  * Wait for the invitation flow to complete and return the target party.
24
24
  */
25
- getParty (): Promise<PartyProxy> {
25
+ getParty (): Promise<Party> {
26
26
  return this.wait();
27
27
  }
28
28
  }
29
29
 
30
30
  export class EchoProxy {
31
31
  private readonly _modelFactory: ModelFactory;
32
- private _parties = new ComplexMap<PublicKey, PartyProxy>(key => key.toHex());
32
+ private _parties = new ComplexMap<PublicKey, Party>(key => key.toHex());
33
33
  private readonly _partiesChanged = new Event();
34
34
  private readonly _subscriptions = new SubscriptionGroup();
35
35
 
@@ -63,12 +63,14 @@ export class EchoProxy {
63
63
  /**
64
64
  * @internal
65
65
  */
66
- _open () {
67
- const partiesStream = this._serviceProvider.services.PartyService.SubscribeParties();
66
+ async _open () {
67
+ const gotParties = this._partiesChanged.waitForCount(1);
68
+
69
+ const partiesStream = this._serviceProvider.services.PartyService.subscribeParties();
68
70
  partiesStream.subscribe(async data => {
69
71
  for (const party of data.parties ?? []) {
70
72
  if (!this._parties.has(party.publicKey)) {
71
- const partyProxy = new PartyProxy(this._serviceProvider, this._modelFactory, party);
73
+ const partyProxy = new Party(this._serviceProvider, this._modelFactory, party);
72
74
  await partyProxy.init();
73
75
  this._parties.set(partyProxy.key, partyProxy);
74
76
 
@@ -79,7 +81,7 @@ export class EchoProxy {
79
81
  }
80
82
  });
81
83
 
82
- const partyStream = this._serviceProvider.services.PartyService.SubscribeToParty({ partyKey: party.publicKey });
84
+ const partyStream = this._serviceProvider.services.PartyService.subscribeToParty({ partyKey: party.publicKey });
83
85
  partyStream.subscribe(async ({ party }) => {
84
86
  if (!party) {
85
87
  return;
@@ -94,6 +96,8 @@ export class EchoProxy {
94
96
  this._partiesChanged.emit();
95
97
  }, () => {});
96
98
  this._subscriptions.push(() => partiesStream.close());
99
+
100
+ await gotParties;
97
101
  }
98
102
 
99
103
  /**
@@ -114,10 +118,10 @@ export class EchoProxy {
114
118
  /**
115
119
  * Creates a new party.
116
120
  */
117
- async createParty (): Promise<PartyProxy> {
121
+ async createParty (): Promise<Party> {
118
122
  const [partyReceivedPromise, partyReceived] = latch();
119
123
 
120
- const party = await this._serviceProvider.services.PartyService.CreateParty();
124
+ const party = await this._serviceProvider.services.PartyService.createParty();
121
125
 
122
126
  const handler = () => {
123
127
  if (this._parties.has(party.publicKey)) {
@@ -135,10 +139,10 @@ export class EchoProxy {
135
139
  /**
136
140
  * Clones the party from a snapshot.
137
141
  */
138
- async cloneParty (snapshot: PartySnapshot): Promise<PartyProxy> {
142
+ async cloneParty (snapshot: PartySnapshot): Promise<Party> {
139
143
  const [partyReceivedPromise, partyReceived] = latch();
140
144
 
141
- const party = await this._serviceProvider.services.PartyService.CloneParty(snapshot);
145
+ const party = await this._serviceProvider.services.PartyService.cloneParty(snapshot);
142
146
 
143
147
  const handler = () => {
144
148
  if (this._parties.has(party.publicKey)) {
@@ -156,11 +160,11 @@ export class EchoProxy {
156
160
  /**
157
161
  * Returns an individual party by its key.
158
162
  */
159
- getParty (partyKey: PartyKey): PartyProxy | undefined {
163
+ getParty (partyKey: PartyKey): Party | undefined {
160
164
  return this._parties.get(partyKey);
161
165
  }
162
166
 
163
- queryParties (): ResultSet<PartyProxy> {
167
+ queryParties (): ResultSet<Party> {
164
168
  return new ResultSet(this._partiesChanged, () => Array.from(this._parties.values()));
165
169
  }
166
170
 
@@ -170,12 +174,12 @@ export class EchoProxy {
170
174
  * To be used with `party.createInvitation` on the inviter side.
171
175
  */
172
176
  acceptInvitation (invitationDescriptor: InvitationDescriptor): PartyInvitation {
173
- const invitationProcessStream = this._serviceProvider.services.PartyService.AcceptInvitation(invitationDescriptor.toProto());
177
+ const invitationProcessStream = this._serviceProvider.services.PartyService.acceptInvitation(invitationDescriptor.toProto());
174
178
  const { authenticate, waitForFinish } = InvitationProxy.handleInvitationRedemption({
175
179
  stream: invitationProcessStream,
176
180
  invitationDescriptor,
177
181
  onAuthenticate: async (request) => {
178
- await this._serviceProvider.services.PartyService.AuthenticateInvitation(request);
182
+ await this._serviceProvider.services.PartyService.authenticateInvitation(request);
179
183
  }
180
184
  });
181
185
 
@@ -3,11 +3,12 @@
3
3
  //
4
4
 
5
5
  import { Event } from '@dxos/async';
6
+ import { KeyRecord } from '@dxos/credentials';
6
7
  import { Contact, CreateProfileOptions, InvitationDescriptor, InvitationOptions, PartyMember, ResultSet } from '@dxos/echo-db';
7
8
  import { SubscriptionGroup } from '@dxos/util';
8
9
 
9
10
  import { ClientServiceProvider } from '../interfaces';
10
- import { Profile } from '../proto/gen/dxos/client';
11
+ import { Profile, SignRequest } from '../proto/gen/dxos/client';
11
12
  import { Invitation, InvitationProxy, InvitationRequest } from './invitations';
12
13
 
13
14
  export interface CreateInvitationOptions extends InvitationOptions {
@@ -42,7 +43,7 @@ export class HaloProxy extends InvitationProxy {
42
43
  * Reset the identity and delete all key records.
43
44
  */
44
45
  async reset () {
45
- await this._serviceProvider.services.SystemService.Reset();
46
+ await this._serviceProvider.services.SystemService.reset();
46
47
  this._profileChanged.emit();
47
48
  }
48
49
 
@@ -57,7 +58,7 @@ export class HaloProxy extends InvitationProxy {
57
58
  * @returns User profile info.
58
59
  */
59
60
  async createProfile ({ publicKey, secretKey, username }: CreateProfileOptions = {}): Promise<Profile> {
60
- this._profile = await this._serviceProvider.services.ProfileService.CreateProfile({ publicKey, secretKey, username });
61
+ this._profile = await this._serviceProvider.services.ProfileService.createProfile({ publicKey, secretKey, username });
61
62
  return this._profile;
62
63
  }
63
64
 
@@ -72,7 +73,7 @@ export class HaloProxy extends InvitationProxy {
72
73
  * Joins an existing identity HALO from a recovery seed phrase.
73
74
  */
74
75
  async recoverProfile (seedPhrase: string) {
75
- this._profile = await this._serviceProvider.services.ProfileService.RecoverProfile({ seedPhrase });
76
+ this._profile = await this._serviceProvider.services.ProfileService.recoverProfile({ seedPhrase });
76
77
  return this._profile;
77
78
  }
78
79
 
@@ -85,7 +86,7 @@ export class HaloProxy extends InvitationProxy {
85
86
  * To be used with `client.halo.joinHaloInvitation` on the invitee side.
86
87
  */
87
88
  async createInvitation (): Promise<InvitationRequest> {
88
- const stream = await this._serviceProvider.services.ProfileService.CreateInvitation();
89
+ const stream = await this._serviceProvider.services.ProfileService.createInvitation();
89
90
  return this.createInvitationRequest({ stream });
90
91
  }
91
92
 
@@ -98,12 +99,12 @@ export class HaloProxy extends InvitationProxy {
98
99
  * To be used with `client.halo.createHaloInvitation` on the inviter side.
99
100
  */
100
101
  acceptInvitation (invitationDescriptor: InvitationDescriptor): Invitation {
101
- const invitationProcessStream = this._serviceProvider.services.ProfileService.AcceptInvitation(invitationDescriptor.toProto());
102
+ const invitationProcessStream = this._serviceProvider.services.ProfileService.acceptInvitation(invitationDescriptor.toProto());
102
103
  const { authenticate, waitForFinish } = InvitationProxy.handleInvitationRedemption({
103
104
  stream: invitationProcessStream,
104
105
  invitationDescriptor,
105
106
  onAuthenticate: async (request) => {
106
- await this._serviceProvider.services.ProfileService.AuthenticateInvitation(request);
107
+ await this._serviceProvider.services.ProfileService.authenticateInvitation(request);
107
108
  }
108
109
  });
109
110
 
@@ -119,25 +120,38 @@ export class HaloProxy extends InvitationProxy {
119
120
  );
120
121
  }
121
122
 
123
+ async addKeyRecord (keyRecord: KeyRecord) {
124
+ await this._serviceProvider.services.HaloService.addKeyRecord({ keyRecord });
125
+ }
126
+
127
+ async sign (request: SignRequest) {
128
+ return await this._serviceProvider.services.HaloService.sign(request);
129
+ }
130
+
122
131
  /**
123
132
  * Allocate resources and set-up internal subscriptions.
124
133
  *
125
134
  * @internal
126
135
  */
127
- _open () {
128
- const profileStream = this._serviceProvider.services.ProfileService.SubscribeProfile();
136
+ async _open () {
137
+ const gotProfile = this._profileChanged.waitForCount(1);
138
+ const gotContacts = this._contactsChanged.waitForCount(1);
139
+
140
+ const profileStream = this._serviceProvider.services.ProfileService.subscribeProfile();
129
141
  profileStream.subscribe(data => {
130
142
  this._profile = data.profile;
131
143
  this._profileChanged.emit();
132
144
  }, () => {});
133
145
  this._subscriptions.push(() => profileStream.close());
134
146
 
135
- const contactsStream = this._serviceProvider.services.ProfileService.SubscribeContacts();
147
+ const contactsStream = this._serviceProvider.services.HaloService.subscribeContacts();
136
148
  contactsStream.subscribe(data => {
137
149
  this._contacts = data.contacts as PartyMember[];
138
150
  this._contactsChanged.emit();
139
151
  }, () => {});
140
152
  this._subscriptions.push(() => contactsStream.close());
153
+
154
+ await Promise.all([gotProfile, gotContacts]);
141
155
  }
142
156
 
143
157
  /**
@@ -5,7 +5,7 @@
5
5
  import { PublicKey } from '@dxos/crypto';
6
6
  import { failUndefined } from '@dxos/debug';
7
7
  import {
8
- ActivationOptions, Database, PARTY_ITEM_TYPE, PARTY_TITLE_PROPERTY, RemoteDatabaseBackend
8
+ ActivationOptions, Database, PARTY_ITEM_TYPE, PARTY_TITLE_PROPERTY, RemoteDatabaseBackend, RootSelector
9
9
  } from '@dxos/echo-db';
10
10
  import { PartyKey } from '@dxos/echo-protocol';
11
11
  import { ModelFactory } from '@dxos/model-factory';
@@ -13,7 +13,7 @@ import { ModelFactory } from '@dxos/model-factory';
13
13
  import { ClientServiceHost } from '../client/service-host';
14
14
  import { ClientServiceProxy } from '../client/service-proxy';
15
15
  import { ClientServiceProvider } from '../interfaces';
16
- import { Party } from '../proto/gen/dxos/client';
16
+ import { Party as PartyProto } from '../proto/gen/dxos/client';
17
17
  import { streamToResultSet } from '../util';
18
18
  import { InvitationRequest, InvitationProxy } from './invitations';
19
19
 
@@ -21,17 +21,20 @@ export interface CreationInvitationOptions {
21
21
  inviteeKey?: PublicKey
22
22
  }
23
23
 
24
- export class PartyProxy extends InvitationProxy {
24
+ export class Party extends InvitationProxy {
25
25
  private readonly _database?: Database;
26
26
 
27
27
  private _key: PartyKey;
28
28
  private _isOpen: boolean;
29
29
  private _isActive: boolean;
30
30
 
31
+ /**
32
+ * @internal
33
+ */
31
34
  constructor (
32
35
  private _serviceProvider: ClientServiceProvider,
33
36
  private _modelFactory: ModelFactory,
34
- _party: Party
37
+ _party: PartyProto
35
38
  ) {
36
39
  super();
37
40
  this._key = _party.publicKey;
@@ -72,7 +75,7 @@ export class PartyProxy extends InvitationProxy {
72
75
  * Called by EchoProxy to update this party instance.
73
76
  * @internal
74
77
  */
75
- _processPartyUpdate (party: Party) {
78
+ _processPartyUpdate (party: PartyProto) {
76
79
  this._key = party.publicKey;
77
80
  this._isOpen = party.isOpen;
78
81
  this._isActive = party.isActive;
@@ -106,7 +109,7 @@ export class PartyProxy extends InvitationProxy {
106
109
  }
107
110
 
108
111
  async setOpen (open: boolean) {
109
- await this._serviceProvider.services.PartyService.SetPartyState({
112
+ await this._serviceProvider.services.PartyService.setPartyState({
110
113
  partyKey: this.key,
111
114
  open
112
115
  });
@@ -115,13 +118,20 @@ export class PartyProxy extends InvitationProxy {
115
118
  async setActive (active: boolean, options: ActivationOptions) {
116
119
  const activeGlobal = options.global ? active : undefined;
117
120
  const activeDevice = options.device ? active : undefined;
118
- await this._serviceProvider.services.PartyService.SetPartyState({
121
+ await this._serviceProvider.services.PartyService.setPartyState({
119
122
  partyKey: this.key,
120
123
  activeGlobal,
121
124
  activeDevice
122
125
  });
123
126
  }
124
127
 
128
+ /**
129
+ * Returns a selection context, which can be used to traverse the object graph.
130
+ */
131
+ get select (): RootSelector {
132
+ return this.database.select.bind(this.database);
133
+ }
134
+
125
135
  /**
126
136
  * Creates an invitation to a given party.
127
137
  * The Invitation flow requires the inviter and invitee to be online at the same time.
@@ -133,13 +143,13 @@ export class PartyProxy extends InvitationProxy {
133
143
  * @param inviteeKey Public key of the invitee. In this case no secret exchange is required, but only the specified recipient can accept the invitation.
134
144
  */
135
145
  async createInvitation ({ inviteeKey }: CreationInvitationOptions = {}): Promise<InvitationRequest> {
136
- const stream = this._serviceProvider.services.PartyService.CreateInvitation({ partyKey: this.key, inviteeKey });
146
+ const stream = this._serviceProvider.services.PartyService.createInvitation({ partyKey: this.key, inviteeKey });
137
147
  return this.createInvitationRequest({ stream });
138
148
  }
139
149
 
140
150
  queryMembers () {
141
151
  return streamToResultSet(
142
- this._serviceProvider.services.PartyService.SubscribeMembers({ partyKey: this.key }),
152
+ this._serviceProvider.services.PartyService.subscribeMembers({ partyKey: this.key }),
143
153
  (response) => response?.members ?? []
144
154
  );
145
155
  }
@@ -161,11 +171,11 @@ export class PartyProxy extends InvitationProxy {
161
171
  }
162
172
 
163
173
  private getPropertiesItem () {
164
- const items = this.database.select(s => s.filter({ type: PARTY_ITEM_TYPE }).items).getValue();
174
+ const items = this.database.select({ type: PARTY_ITEM_TYPE }).query().result;
165
175
  return items[0];
166
176
  }
167
177
 
168
178
  createSnapshot () {
169
- return this._serviceProvider.services.PartyService.CreateSnapshot({ partyKey: this.key });
179
+ return this._serviceProvider.services.PartyService.createSnapshot({ partyKey: this.key });
170
180
  }
171
181
  }
@@ -31,24 +31,24 @@ describe('Client Services', () => {
31
31
  const invitee = await setup();
32
32
  afterTest(() => invitee.client.destroy());
33
33
 
34
- await inviter.services.ProfileService.CreateProfile({ username: 'test-user' });
34
+ await inviter.services.ProfileService.createProfile({ username: 'test-user' });
35
35
 
36
36
  const invitation = await new Promise<InvitationRequest>((resolve, reject) => {
37
- inviter.services.ProfileService.CreateInvitation().subscribe(resolve, reject);
37
+ inviter.services.ProfileService.createInvitation().subscribe(resolve, reject);
38
38
  });
39
39
  assert(invitation.descriptor);
40
40
 
41
41
  const redeemedInvitation = await new Promise<RedeemedInvitation>((resolve, reject) => {
42
- invitee.services.ProfileService.AcceptInvitation(invitation.descriptor!).subscribe(resolve, reject);
42
+ invitee.services.ProfileService.acceptInvitation(invitation.descriptor!).subscribe(resolve, reject);
43
43
  });
44
44
 
45
- await invitee.services.ProfileService.AuthenticateInvitation({
45
+ await invitee.services.ProfileService.authenticateInvitation({
46
46
  processId: redeemedInvitation.id,
47
47
  secret: invitation.descriptor.secret
48
48
  });
49
49
 
50
50
  const [inviteeProfileLatch, inviteeProfileTrigger] = latch();
51
- invitee.services.ProfileService.SubscribeProfile().subscribe(inviteeProfile => {
51
+ invitee.services.ProfileService.subscribeProfile().subscribe(inviteeProfile => {
52
52
  if (inviteeProfile.profile?.username === 'test-user') {
53
53
  inviteeProfileTrigger();
54
54
  }
@@ -309,8 +309,8 @@ describe('Client', () => {
309
309
  client.registerModel(TestModel);
310
310
 
311
311
  const party = client.echo.queryParties().first;
312
- const selection = party.database.select(s => s.filter({ type: 'test' }).items);
313
- await selection.update.waitForCondition(() => selection.getValue().length > 0);
312
+ const selection = party.database.select({ type: 'test' }).query();
313
+ await selection.update.waitForCondition(() => selection.result.length > 0);
314
314
 
315
315
  const item = selection.expectOne();
316
316
 
@@ -169,8 +169,8 @@ export class Client {
169
169
  this._halo = new HaloProxy(this._serviceProvider);
170
170
  this._echo = new EchoProxy(this._serviceProvider);
171
171
 
172
- this._halo._open();
173
- this._echo._open();
172
+ await this._halo._open();
173
+ await this._echo._open();
174
174
 
175
175
  this._initialized = true; // TODO(burdon): Initialized === halo.initialized?
176
176
  clearInterval(timeout);
@@ -233,7 +233,7 @@ export class Client {
233
233
  // Recreate echo instance? Big impact on hooks. Test.
234
234
  @synchronized
235
235
  async reset () {
236
- await this.services.SystemService.Reset();
236
+ await this.services.SystemService.reset();
237
237
  this._initialized = false;
238
238
  }
239
239
 
@@ -0,0 +1,80 @@
1
+ //
2
+ // Copyright 2022 DXOS.org
3
+ //
4
+
5
+ import PolkadotKeyring from '@polkadot/keyring';
6
+ import { hexToU8a, u8aToHex } from '@polkadot/util';
7
+ import { cryptoWaitReady } from '@polkadot/util-crypto';
8
+ import assert from 'assert';
9
+
10
+ import { Stream } from '@dxos/codec-protobuf';
11
+ import { KeyRecord, KeyType } from '@dxos/credentials';
12
+ import { ECHO } from '@dxos/echo-db';
13
+ import { SubscriptionGroup } from '@dxos/util';
14
+
15
+ import { AddKeyRecordRequest, Contacts, HaloService as IHaloService, SignRequest, SignResponse } from '../../../proto/gen/dxos/client';
16
+ import { resultSetToStream } from '../../../util';
17
+ import { CreateServicesOpts } from './interfaces';
18
+
19
+ export class HaloService implements IHaloService {
20
+ constructor (private echo: ECHO) {}
21
+
22
+ subscribeContacts (): Stream<Contacts> {
23
+ if (this.echo.halo.isInitialized) {
24
+ return resultSetToStream(this.echo.halo.queryContacts(), (contacts): Contacts => ({ contacts }));
25
+ } else {
26
+ return new Stream(({ next }) => {
27
+ // If profile does not exist, send an empty array.
28
+ if (!this.echo.halo.isInitialized) {
29
+ next({ contacts: [] });
30
+ }
31
+
32
+ const subGroup = new SubscriptionGroup();
33
+
34
+ setImmediate(async () => {
35
+ await this.echo.halo.identityReady.waitForCondition(() => this.echo.halo.isInitialized);
36
+
37
+ const resultSet = this.echo.halo.queryContacts();
38
+ next({ contacts: resultSet.value });
39
+ subGroup.push(resultSet.update.on(() => next({ contacts: resultSet.value })));
40
+ });
41
+
42
+ return () => subGroup.unsubscribe();
43
+ });
44
+ }
45
+ }
46
+
47
+ async addKeyRecord (request: AddKeyRecordRequest): Promise<void> {
48
+ assert(request.keyRecord && request.keyRecord.publicKey, 'Missing key record.');
49
+ await this.echo.halo.keyring.addKeyRecord(request.keyRecord);
50
+ assert(await this.echo.halo.keyring.getKey(request.keyRecord.publicKey), 'Key not inserted correctly.');
51
+ }
52
+
53
+ private async polkadotSign (key: KeyRecord, payload: SignRequest['payload']): Promise<SignResponse> {
54
+ await cryptoWaitReady();
55
+
56
+ assert(key.secretKey, 'Secret key is missing.');
57
+
58
+ const keyring = new PolkadotKeyring({ type: 'sr25519' });
59
+ const keypair = keyring.addFromUri(key.secretKey.toString());
60
+
61
+ const signature = u8aToHex(keypair.sign(hexToU8a(payload), { withType: true }));
62
+ return {
63
+ signed: signature
64
+ };
65
+ }
66
+
67
+ async sign (request: SignRequest): Promise<SignResponse> {
68
+ assert(request.publicKey, 'Provide a publicKey of the key that should be used for signing.');
69
+ const key = await this.echo.halo.keyring.getFullKey(request.publicKey);
70
+ assert(key, 'Key not found.');
71
+ if (key.type === KeyType.DXNS) {
72
+ return this.polkadotSign(key, request.payload);
73
+ }
74
+ throw new Error('Only DXNS key signing is supported.');
75
+ }
76
+ }
77
+
78
+ export const createHaloService = ({ echo }: CreateServicesOpts): HaloService => {
79
+ return new HaloService(echo);
80
+ };
@@ -8,8 +8,8 @@ import { v4 } from 'uuid';
8
8
  import { latch } from '@dxos/async';
9
9
  import { Stream } from '@dxos/codec-protobuf';
10
10
  import { defaultSecretValidator, generatePasscode, SecretProvider } from '@dxos/credentials';
11
- import { raise } from '@dxos/debug';
12
- import { ECHO, EchoNotOpenError, InvitationDescriptor, InvitationDescriptorType, PartyNotFoundError } from '@dxos/echo-db';
11
+ import { InvalidStateError, raise } from '@dxos/debug';
12
+ import { ECHO, InvitationDescriptor, InvitationDescriptorType, PartyNotFoundError } from '@dxos/echo-db';
13
13
 
14
14
  import {
15
15
  InvitationState,
@@ -37,7 +37,7 @@ class PartyService implements IPartyService {
37
37
 
38
38
  constructor (private echo: ECHO) {}
39
39
 
40
- SubscribeToParty (request: SubscribePartyRequest): Stream<SubscribePartyResponse> {
40
+ subscribeToParty (request: SubscribePartyRequest): Stream<SubscribePartyResponse> {
41
41
  const update = (next: (message: SubscribePartyResponse) => void) => {
42
42
  try {
43
43
  const party = this.echo.getParty(request.partyKey);
@@ -50,7 +50,7 @@ class PartyService implements IPartyService {
50
50
  }
51
51
  });
52
52
  } catch (error) {
53
- if (error instanceof EchoNotOpenError) {
53
+ if (error instanceof InvalidStateError) {
54
54
  // Do nothing.
55
55
  } else {
56
56
  throw error;
@@ -83,7 +83,7 @@ class PartyService implements IPartyService {
83
83
  }
84
84
  }
85
85
 
86
- SubscribeParties () {
86
+ subscribeParties () {
87
87
  return resultSetToStream(this.echo.queryParties(), (parties): SubscribePartiesResponse => {
88
88
  return ({
89
89
  parties: parties.map(party => ({
@@ -96,7 +96,7 @@ class PartyService implements IPartyService {
96
96
  });
97
97
  }
98
98
 
99
- async CreateParty () {
99
+ async createParty () {
100
100
  const party = await this.echo.createParty();
101
101
  return {
102
102
  publicKey: party.key,
@@ -105,7 +105,7 @@ class PartyService implements IPartyService {
105
105
  };
106
106
  }
107
107
 
108
- async CloneParty (snapshot: PartySnapshot): Promise<Party> {
108
+ async cloneParty (snapshot: PartySnapshot): Promise<Party> {
109
109
  const party = await this.echo.cloneParty(snapshot);
110
110
  return {
111
111
  publicKey: party.key,
@@ -114,7 +114,7 @@ class PartyService implements IPartyService {
114
114
  };
115
115
  }
116
116
 
117
- async SetPartyState (request: SetPartyStateRequest) {
117
+ async setPartyState (request: SetPartyStateRequest) {
118
118
  const party = this.echo.getParty(request.partyKey);
119
119
  if (!party) {
120
120
  throw new Error('Party not found');
@@ -144,7 +144,7 @@ class PartyService implements IPartyService {
144
144
  };
145
145
  }
146
146
 
147
- CreateInvitation (request: CreateInvitationRequest): Stream<InvitationRequest> {
147
+ createInvitation (request: CreateInvitationRequest): Stream<InvitationRequest> {
148
148
  return new Stream(({ next, close }) => {
149
149
  const party = this.echo.getParty(request.partyKey) ?? raise(new PartyNotFoundError(request.partyKey));
150
150
  setImmediate(async () => {
@@ -156,7 +156,7 @@ class PartyService implements IPartyService {
156
156
  next({ state: InvitationState.CONNECTED });
157
157
  return Buffer.from(secret);
158
158
  };
159
- invitation = await party.createInvitation({
159
+ invitation = await party.invitationManager.createInvitation({
160
160
  secretProvider,
161
161
  secretValidator: defaultSecretValidator
162
162
  }, {
@@ -169,7 +169,7 @@ class PartyService implements IPartyService {
169
169
  assert(invitation.type === InvitationDescriptorType.INTERACTIVE);
170
170
  invitation.secret = Buffer.from(secret);
171
171
  } else {
172
- invitation = await party.createOfflineInvitation(request.inviteeKey);
172
+ invitation = await party.invitationManager.createOfflineInvitation(request.inviteeKey);
173
173
  }
174
174
 
175
175
  next({ state: InvitationState.WAITING_FOR_CONNECTION, descriptor: invitation.toProto() });
@@ -185,7 +185,7 @@ class PartyService implements IPartyService {
185
185
  });
186
186
  }
187
187
 
188
- AcceptInvitation (request: InvitationDescriptorProto): Stream<RedeemedInvitation> {
188
+ acceptInvitation (request: InvitationDescriptorProto): Stream<RedeemedInvitation> {
189
189
  return new Stream(({ next, close }) => {
190
190
  const id = v4();
191
191
  const [secretLatch, secretTrigger] = latch();
@@ -221,7 +221,7 @@ class PartyService implements IPartyService {
221
221
  });
222
222
  }
223
223
 
224
- async AuthenticateInvitation (request: AuthenticateInvitationRequest) {
224
+ async authenticateInvitation (request: AuthenticateInvitationRequest) {
225
225
  assert(request.processId, 'Process ID is missing.');
226
226
  const invitation = this.inviteeInvitations.get(request.processId);
227
227
  assert(invitation, 'Invitation not found.');
@@ -232,7 +232,7 @@ class PartyService implements IPartyService {
232
232
  invitation.secretTrigger?.();
233
233
  }
234
234
 
235
- SubscribeMembers (request: SubscribeMembersRequest): Stream<SubscribeMembersResponse> {
235
+ subscribeMembers (request: SubscribeMembersRequest): Stream<SubscribeMembersResponse> {
236
236
  const party = this.echo.getParty(request.partyKey);
237
237
  if (party) {
238
238
  return resultSetToStream(party.queryMembers(), (members): SubscribeMembersResponse => ({ members }));
@@ -256,7 +256,7 @@ class PartyService implements IPartyService {
256
256
  }
257
257
  }
258
258
 
259
- CreateSnapshot (request: CreateSnaspotRequest): Promise<PartySnapshot> {
259
+ async createSnapshot (request: CreateSnaspotRequest): Promise<PartySnapshot> {
260
260
  assert(request.partyKey);
261
261
  const party = this.echo.getParty(request.partyKey) ?? raise(new PartyNotFoundError(request.partyKey));
262
262
  return party.createSnapshot();