@dxos/client-services 0.4.10-main.fd4f2a3 → 0.4.10-main.fd8ea31

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 (97) hide show
  1. package/dist/lib/browser/{chunk-V2ALN47T.mjs → chunk-WLE7E36I.mjs} +1402 -1074
  2. package/dist/lib/browser/chunk-WLE7E36I.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +13 -3
  4. package/dist/lib/browser/index.mjs.map +1 -1
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/packlets/testing/index.mjs +133 -115
  7. package/dist/lib/browser/packlets/testing/index.mjs.map +3 -3
  8. package/dist/lib/node/{chunk-7WXQVUAE.cjs → chunk-YXZQQAQN.cjs} +1308 -1063
  9. package/dist/lib/node/chunk-YXZQQAQN.cjs.map +7 -0
  10. package/dist/lib/node/index.cjs +49 -39
  11. package/dist/lib/node/index.cjs.map +1 -1
  12. package/dist/lib/node/meta.json +1 -1
  13. package/dist/lib/node/packlets/testing/index.cjs +133 -118
  14. package/dist/lib/node/packlets/testing/index.cjs.map +3 -3
  15. package/dist/types/src/index.d.ts +1 -0
  16. package/dist/types/src/index.d.ts.map +1 -1
  17. package/dist/types/src/packlets/diagnostics/browser-diagnostics-broadcast.d.ts +5 -0
  18. package/dist/types/src/packlets/diagnostics/browser-diagnostics-broadcast.d.ts.map +1 -0
  19. package/dist/types/src/packlets/diagnostics/diagnostics-broadcast.d.ts +5 -0
  20. package/dist/types/src/packlets/diagnostics/diagnostics-broadcast.d.ts.map +1 -0
  21. package/dist/types/src/packlets/diagnostics/diagnostics-collector.d.ts +15 -0
  22. package/dist/types/src/packlets/diagnostics/diagnostics-collector.d.ts.map +1 -0
  23. package/dist/types/src/packlets/{services → diagnostics}/diagnostics.d.ts +1 -1
  24. package/dist/types/src/packlets/diagnostics/diagnostics.d.ts.map +1 -0
  25. package/dist/types/src/packlets/diagnostics/index.d.ts +4 -0
  26. package/dist/types/src/packlets/diagnostics/index.d.ts.map +1 -0
  27. package/dist/types/src/packlets/identity/identity-manager.d.ts.map +1 -1
  28. package/dist/types/src/packlets/indexing/util.d.ts +2 -6
  29. package/dist/types/src/packlets/indexing/util.d.ts.map +1 -1
  30. package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts +3 -1
  31. package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts.map +1 -1
  32. package/dist/types/src/packlets/invitations/index.d.ts +1 -0
  33. package/dist/types/src/packlets/invitations/index.d.ts.map +1 -1
  34. package/dist/types/src/packlets/invitations/invitation-extension.d.ts +1 -0
  35. package/dist/types/src/packlets/invitations/invitation-extension.d.ts.map +1 -1
  36. package/dist/types/src/packlets/invitations/invitation-protocol.d.ts +6 -1
  37. package/dist/types/src/packlets/invitations/invitation-protocol.d.ts.map +1 -1
  38. package/dist/types/src/packlets/invitations/invitations-handler.d.ts +8 -4
  39. package/dist/types/src/packlets/invitations/invitations-handler.d.ts.map +1 -1
  40. package/dist/types/src/packlets/invitations/invitations-manager.d.ts +44 -0
  41. package/dist/types/src/packlets/invitations/invitations-manager.d.ts.map +1 -0
  42. package/dist/types/src/packlets/invitations/invitations-service.d.ts +7 -23
  43. package/dist/types/src/packlets/invitations/invitations-service.d.ts.map +1 -1
  44. package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts +2 -1
  45. package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts.map +1 -1
  46. package/dist/types/src/packlets/services/index.d.ts +1 -1
  47. package/dist/types/src/packlets/services/index.d.ts.map +1 -1
  48. package/dist/types/src/packlets/services/service-context.d.ts +2 -0
  49. package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
  50. package/dist/types/src/packlets/services/service-host.d.ts +5 -1
  51. package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
  52. package/dist/types/src/packlets/services/util.d.ts +1 -0
  53. package/dist/types/src/packlets/services/util.d.ts.map +1 -1
  54. package/dist/types/src/packlets/spaces/data-space-manager.d.ts +5 -1
  55. package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
  56. package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
  57. package/dist/types/src/packlets/system/system-service.d.ts +1 -1
  58. package/dist/types/src/packlets/system/system-service.d.ts.map +1 -1
  59. package/dist/types/src/packlets/testing/invitation-utils.d.ts.map +1 -1
  60. package/dist/types/src/packlets/testing/test-builder.d.ts +6 -1
  61. package/dist/types/src/packlets/testing/test-builder.d.ts.map +1 -1
  62. package/dist/types/src/version.d.ts +1 -1
  63. package/package.json +35 -34
  64. package/src/index.ts +1 -0
  65. package/src/packlets/diagnostics/browser-diagnostics-broadcast.ts +94 -0
  66. package/src/packlets/diagnostics/diagnostics-broadcast.ts +20 -0
  67. package/src/packlets/diagnostics/diagnostics-collector.ts +65 -0
  68. package/src/packlets/{services → diagnostics}/diagnostics.ts +2 -2
  69. package/src/packlets/diagnostics/index.ts +7 -0
  70. package/src/packlets/identity/identity-manager.ts +1 -0
  71. package/src/packlets/identity/identity.test.ts +3 -0
  72. package/src/packlets/indexing/util.ts +9 -66
  73. package/src/packlets/invitations/device-invitation-protocol.ts +6 -1
  74. package/src/packlets/invitations/index.ts +1 -0
  75. package/src/packlets/invitations/invitation-extension.ts +28 -1
  76. package/src/packlets/invitations/invitation-protocol.ts +7 -1
  77. package/src/packlets/invitations/invitations-handler.ts +75 -96
  78. package/src/packlets/invitations/invitations-manager.ts +271 -0
  79. package/src/packlets/invitations/invitations-service.ts +23 -168
  80. package/src/packlets/invitations/space-invitation-protocol.ts +45 -3
  81. package/src/packlets/services/automerge-host.test.ts +10 -4
  82. package/src/packlets/services/index.ts +1 -1
  83. package/src/packlets/services/service-context.test.ts +4 -1
  84. package/src/packlets/services/service-context.ts +19 -5
  85. package/src/packlets/services/service-host.ts +34 -19
  86. package/src/packlets/services/util.ts +2 -0
  87. package/src/packlets/spaces/data-space-manager.test.ts +4 -4
  88. package/src/packlets/spaces/data-space-manager.ts +48 -2
  89. package/src/packlets/spaces/data-space.ts +1 -1
  90. package/src/packlets/storage/level.ts +1 -1
  91. package/src/packlets/system/system-service.ts +1 -1
  92. package/src/packlets/testing/invitation-utils.ts +100 -97
  93. package/src/packlets/testing/test-builder.ts +39 -5
  94. package/src/version.ts +1 -1
  95. package/dist/lib/browser/chunk-V2ALN47T.mjs.map +0 -7
  96. package/dist/lib/node/chunk-7WXQVUAE.cjs.map +0 -7
  97. package/dist/types/src/packlets/services/diagnostics.d.ts.map +0 -1
@@ -5,6 +5,8 @@
5
5
  import { PublicKey } from '@dxos/keys';
6
6
  import { humanize } from '@dxos/util';
7
7
 
8
+ export const ClientServicesProviderResource = Symbol.for('dxos.resource.ClientServices');
9
+
8
10
  // TODO(burdon): Move to util.
9
11
 
10
12
  export type JsonStringifyOptions = {
@@ -20,7 +20,7 @@ describe('DataSpaceManager', () => {
20
20
 
21
21
  const peer = builder.createPeer();
22
22
  await peer.createIdentity();
23
- await openAndClose(peer.dataSpaceManager);
23
+ await openAndClose(peer.automergeHost, peer.dataSpaceManager);
24
24
 
25
25
  const space = await peer.dataSpaceManager.createSpace();
26
26
 
@@ -42,7 +42,7 @@ describe('DataSpaceManager', () => {
42
42
  const peer2 = builder.createPeer();
43
43
  await peer2.createIdentity();
44
44
 
45
- await openAndClose(peer1.dataSpaceManager, peer2.dataSpaceManager);
45
+ await openAndClose(peer1.automergeHost, peer1.dataSpaceManager, peer2.automergeHost, peer2.dataSpaceManager);
46
46
 
47
47
  const space1 = await peer1.dataSpaceManager.createSpace();
48
48
  await space1.inner.controlPipeline.state.waitUntilTimeframe(space1.inner.controlPipeline.state.endTimeframe);
@@ -111,7 +111,7 @@ describe('DataSpaceManager', () => {
111
111
  await peer2.createIdentity();
112
112
  await peer2.dataSpaceManager.open();
113
113
 
114
- await openAndClose(peer1.dataSpaceManager, peer2.dataSpaceManager);
114
+ await openAndClose(peer1.automergeHost, peer1.dataSpaceManager, peer2.automergeHost, peer2.dataSpaceManager);
115
115
 
116
116
  const space1 = await peer1.dataSpaceManager.createSpace();
117
117
  await space1.inner.controlPipeline.state.waitUntilTimeframe(space1.inner.controlPipeline.state.endTimeframe);
@@ -153,7 +153,7 @@ describe('DataSpaceManager', () => {
153
153
 
154
154
  const peer = builder.createPeer();
155
155
  await peer.createIdentity();
156
- await openAndClose(peer.dataSpaceManager);
156
+ await openAndClose(peer.automergeHost, peer.dataSpaceManager);
157
157
 
158
158
  const space = await peer.dataSpaceManager.createSpace();
159
159
  await space.inner.controlPipeline.state.waitUntilTimeframe(space.inner.controlPipeline.state.endTimeframe);
@@ -4,7 +4,7 @@
4
4
 
5
5
  import { Event, synchronized, trackLeaks } from '@dxos/async';
6
6
  import { Context, cancelWithContext } from '@dxos/context';
7
- import { getCredentialAssertion, type CredentialSigner } from '@dxos/credentials';
7
+ import { getCredentialAssertion, type CredentialSigner, type DelegateInvitationCredential } from '@dxos/credentials';
8
8
  import { type AutomergeHost, type MetadataStore, type Space, type SpaceManager } from '@dxos/echo-pipeline';
9
9
  import { type FeedStore } from '@dxos/feed-store';
10
10
  import { invariant } from '@dxos/invariant';
@@ -12,10 +12,11 @@ import { type Keyring } from '@dxos/keyring';
12
12
  import { PublicKey } from '@dxos/keys';
13
13
  import { log } from '@dxos/log';
14
14
  import { trace } from '@dxos/protocols';
15
- import { SpaceState } from '@dxos/protocols/proto/dxos/client/services';
15
+ import { Invitation, SpaceState } from '@dxos/protocols/proto/dxos/client/services';
16
16
  import { type FeedMessage } from '@dxos/protocols/proto/dxos/echo/feed';
17
17
  import { type SpaceMetadata } from '@dxos/protocols/proto/dxos/echo/metadata';
18
18
  import { type Credential, type ProfileDocument } from '@dxos/protocols/proto/dxos/halo/credentials';
19
+ import { type DelegateSpaceInvitation } from '@dxos/protocols/proto/dxos/halo/invitations';
19
20
  import { Gossip, Presence } from '@dxos/teleport-extension-gossip';
20
21
  import { type Timeframe } from '@dxos/timeframe';
21
22
  import { ComplexMap, deferFunction, forEachAsync } from '@dxos/util';
@@ -23,6 +24,7 @@ import { ComplexMap, deferFunction, forEachAsync } from '@dxos/util';
23
24
  import { DataSpace } from './data-space';
24
25
  import { spaceGenesis } from './genesis';
25
26
  import { createAuthProvider } from '../identity';
27
+ import { type InvitationsManager } from '../invitations';
26
28
 
27
29
  const PRESENCE_ANNOUNCE_INTERVAL = 10_000;
28
30
  const PRESENCE_OFFLINE_TIMEOUT = 20_000;
@@ -78,6 +80,7 @@ export class DataSpaceManager {
78
80
  private readonly _signingContext: SigningContext,
79
81
  private readonly _feedStore: FeedStore<FeedMessage>,
80
82
  private readonly _automergeHost: AutomergeHost,
83
+ private readonly _invitationsManager: InvitationsManager,
81
84
  params?: DataSpaceManagerRuntimeParams,
82
85
  ) {
83
86
  const {
@@ -247,6 +250,9 @@ export class DataSpaceManager {
247
250
  log.warn('auth failure');
248
251
  },
249
252
  memberKey: this._signingContext.identityKey,
253
+ onDelegatedInvitationStatusChange: (invitation, isActive) => {
254
+ return this._handleInvitationStatusChange(dataSpace, invitation, isActive);
255
+ },
250
256
  });
251
257
  controlFeed && (await space.setControlFeed(controlFeed));
252
258
  dataFeed && (await space.setDataFeed(dataFeed));
@@ -267,6 +273,7 @@ export class DataSpaceManager {
267
273
  afterReady: async () => {
268
274
  log('after space ready', { space: space.key, open: this._isOpen });
269
275
  if (this._isOpen) {
276
+ await this._createDelegatedInvitations(dataSpace, [...space.spaceState.invitations.entries()]);
270
277
  this.updated.emit();
271
278
  }
272
279
  },
@@ -289,4 +296,43 @@ export class DataSpaceManager {
289
296
  this._spaces.set(metadata.key, dataSpace);
290
297
  return dataSpace;
291
298
  }
299
+
300
+ private async _handleInvitationStatusChange(
301
+ dataSpace: DataSpace | undefined,
302
+ delegatedInvitation: DelegateInvitationCredential,
303
+ isActive: boolean,
304
+ ): Promise<void> {
305
+ if (dataSpace?.state !== SpaceState.READY) {
306
+ return;
307
+ }
308
+ if (isActive) {
309
+ await this._createDelegatedInvitations(dataSpace, [
310
+ [delegatedInvitation.credentialId, delegatedInvitation.invitation],
311
+ ]);
312
+ } else {
313
+ await this._invitationsManager.cancelInvitation(delegatedInvitation.invitation);
314
+ }
315
+ }
316
+
317
+ private async _createDelegatedInvitations(
318
+ space: DataSpace,
319
+ invitations: Array<[PublicKey, DelegateSpaceInvitation]>,
320
+ ): Promise<void> {
321
+ const tasks = invitations.map(([credentialId, invitation]) => {
322
+ return this._invitationsManager.createInvitation({
323
+ type: Invitation.Type.DELEGATED,
324
+ kind: Invitation.Kind.SPACE,
325
+ spaceKey: space.key,
326
+ authMethod: invitation.authMethod,
327
+ invitationId: invitation.invitationId,
328
+ swarmKey: invitation.swarmKey,
329
+ guestKeypair: invitation.guestKey ? { publicKey: invitation.guestKey } : undefined,
330
+ lifetime: invitation.expiresOn ? invitation.expiresOn.getTime() - Date.now() : undefined,
331
+ multiUse: invitation.multiUse,
332
+ delegationCredentialId: credentialId,
333
+ persistent: false,
334
+ });
335
+ });
336
+ await Promise.all(tasks);
337
+ }
292
338
  }
@@ -6,7 +6,6 @@ import { Event, asyncTimeout, scheduleTask, sleep, synchronized, trackLeaks } fr
6
6
  import { AUTH_TIMEOUT } from '@dxos/client-protocol';
7
7
  import { cancelWithContext, Context, ContextDisposedError } from '@dxos/context';
8
8
  import { timed, warnAfterTimeout } from '@dxos/debug';
9
- import { TYPE_PROPERTIES } from '@dxos/echo-db';
10
9
  import {
11
10
  type MetadataStore,
12
11
  type Space,
@@ -15,6 +14,7 @@ import {
15
14
  type SpaceDoc,
16
15
  } from '@dxos/echo-pipeline';
17
16
  import { AutomergeDocumentLoaderImpl } from '@dxos/echo-pipeline';
17
+ import { TYPE_PROPERTIES } from '@dxos/echo-schema';
18
18
  import { type FeedStore } from '@dxos/feed-store';
19
19
  import { failedInvariant, invariant } from '@dxos/invariant';
20
20
  import { type Keyring } from '@dxos/keyring';
@@ -12,7 +12,7 @@ import { getRootPath, isPersistent } from './util';
12
12
 
13
13
  export const createLevel = async (config: Runtime.Client.Storage) => {
14
14
  const persistent = isPersistent(config);
15
- const storagePath = persistent ? getRootPath(config) : path.join('tmp', 'level', PublicKey.random().toHex());
15
+ const storagePath = persistent ? path.join(getRootPath(config), 'level') : `/tmp/dxos-${PublicKey.random().toHex()}`;
16
16
  const level = new Level<string, string>(storagePath);
17
17
  await level.open();
18
18
  return level;
@@ -16,7 +16,7 @@ import {
16
16
  } from '@dxos/protocols/proto/dxos/client/services';
17
17
  import { jsonKeyReplacer, type MaybePromise } from '@dxos/util';
18
18
 
19
- import { type Diagnostics } from '../services';
19
+ import { type Diagnostics } from '../diagnostics';
20
20
  import { getPlatform } from '../services/platform';
21
21
 
22
22
  export type SystemServiceOptions = {
@@ -60,146 +60,149 @@ export const performInvitation = ({
60
60
  const guestComplete = new Trigger<Result>();
61
61
  const authCode = new Trigger<string>();
62
62
 
63
- const hostObservable = createInvitation(host, options);
64
- hostObservable.subscribe(
65
- async (hostInvitation: Invitation) => {
66
- switch (hostInvitation.state) {
67
- case Invitation.State.CONNECTING: {
68
- if (hooks?.host?.onConnecting?.(hostObservable)) {
69
- break;
70
- }
71
- const guestObservable = acceptInvitation(guest, hostInvitation, guestDeviceProfile);
72
- guestObservable.subscribe(
73
- async (guestInvitation: Invitation) => {
74
- switch (guestInvitation.state) {
75
- case Invitation.State.CONNECTING: {
76
- if (hooks?.guest?.onConnecting?.(guestObservable)) {
63
+ void createInvitation(host, options).then((hostObservable) => {
64
+ hostObservable.subscribe(
65
+ async (hostInvitation: Invitation) => {
66
+ switch (hostInvitation.state) {
67
+ case Invitation.State.CONNECTING: {
68
+ if (hooks?.host?.onConnecting?.(hostObservable)) {
69
+ break;
70
+ }
71
+ const guestObservable = acceptInvitation(guest, hostInvitation, guestDeviceProfile);
72
+ guestObservable.subscribe(
73
+ async (guestInvitation: Invitation) => {
74
+ switch (guestInvitation.state) {
75
+ case Invitation.State.CONNECTING: {
76
+ if (hooks?.guest?.onConnecting?.(guestObservable)) {
77
+ break;
78
+ }
79
+ invariant(hostInvitation.swarmKey!.equals(guestInvitation.swarmKey!));
77
80
  break;
78
81
  }
79
- invariant(hostInvitation.swarmKey!.equals(guestInvitation.swarmKey!));
80
- break;
81
- }
82
82
 
83
- case Invitation.State.CONNECTED: {
84
- hooks?.guest?.onConnected?.(guestObservable);
85
- break;
86
- }
83
+ case Invitation.State.CONNECTED: {
84
+ hooks?.guest?.onConnected?.(guestObservable);
85
+ break;
86
+ }
87
87
 
88
- case Invitation.State.READY_FOR_AUTHENTICATION: {
89
- if (hooks?.guest?.onReady?.(guestObservable)) {
88
+ case Invitation.State.READY_FOR_AUTHENTICATION: {
89
+ if (hooks?.guest?.onReady?.(guestObservable)) {
90
+ break;
91
+ }
92
+ await guestObservable.authenticate(await authCode.wait());
90
93
  break;
91
94
  }
92
- await guestObservable.authenticate(await authCode.wait());
93
- break;
94
- }
95
95
 
96
- case Invitation.State.AUTHENTICATING: {
97
- hooks?.guest?.onAuthenticating?.(guestObservable);
98
- break;
99
- }
96
+ case Invitation.State.AUTHENTICATING: {
97
+ hooks?.guest?.onAuthenticating?.(guestObservable);
98
+ break;
99
+ }
100
100
 
101
- case Invitation.State.SUCCESS: {
102
- if (hooks?.guest?.onSuccess?.(guestObservable)) {
101
+ case Invitation.State.SUCCESS: {
102
+ if (hooks?.guest?.onSuccess?.(guestObservable)) {
103
+ break;
104
+ }
105
+ guestComplete.wake({ invitation: guestInvitation });
103
106
  break;
104
107
  }
105
- guestComplete.wake({ invitation: guestInvitation });
106
- break;
107
- }
108
108
 
109
- case Invitation.State.CANCELLED: {
110
- if (hooks?.guest?.onCancelled?.(guestObservable)) {
109
+ case Invitation.State.CANCELLED: {
110
+ if (hooks?.guest?.onCancelled?.(guestObservable)) {
111
+ break;
112
+ }
113
+ guestComplete.wake({ invitation: guestInvitation });
111
114
  break;
112
115
  }
113
- guestComplete.wake({ invitation: guestInvitation });
114
- break;
115
- }
116
116
 
117
- case Invitation.State.TIMEOUT: {
118
- if (hooks?.guest?.onTimeout?.(guestObservable)) {
119
- return;
117
+ case Invitation.State.TIMEOUT: {
118
+ if (hooks?.guest?.onTimeout?.(guestObservable)) {
119
+ return;
120
+ }
121
+ guestComplete.wake({ invitation: guestInvitation });
120
122
  }
121
- guestComplete.wake({ invitation: guestInvitation });
122
123
  }
123
- }
124
- },
125
- (error: Error) => {
126
- if (hooks?.guest?.onError?.(guestObservable)) {
127
- return;
128
- }
129
- guestComplete.wake({ error });
130
- },
131
- );
132
- break;
133
- }
134
-
135
- case Invitation.State.CONNECTED: {
136
- hooks?.host?.onConnected?.(hostObservable);
137
- break;
138
- }
124
+ },
125
+ (error: Error) => {
126
+ if (hooks?.guest?.onError?.(guestObservable)) {
127
+ return;
128
+ }
129
+ guestComplete.wake({ error });
130
+ },
131
+ );
132
+ break;
133
+ }
139
134
 
140
- case Invitation.State.READY_FOR_AUTHENTICATION: {
141
- if (hooks?.host?.onReady?.(hostObservable)) {
135
+ case Invitation.State.CONNECTED: {
136
+ hooks?.host?.onConnected?.(hostObservable);
142
137
  break;
143
138
  }
144
- if (hostInvitation.authCode) {
145
- authCode.wake(hostInvitation.authCode);
139
+
140
+ case Invitation.State.READY_FOR_AUTHENTICATION: {
141
+ if (hooks?.host?.onReady?.(hostObservable)) {
142
+ break;
143
+ }
144
+ if (hostInvitation.authCode) {
145
+ authCode.wake(hostInvitation.authCode);
146
+ }
147
+ break;
146
148
  }
147
- break;
148
- }
149
149
 
150
- case Invitation.State.AUTHENTICATING: {
151
- hooks?.host?.onAuthenticating?.(hostObservable);
152
- break;
153
- }
150
+ case Invitation.State.AUTHENTICATING: {
151
+ hooks?.host?.onAuthenticating?.(hostObservable);
152
+ break;
153
+ }
154
154
 
155
- case Invitation.State.SUCCESS: {
156
- if (hooks?.host?.onSuccess?.(hostObservable)) {
155
+ case Invitation.State.SUCCESS: {
156
+ if (hooks?.host?.onSuccess?.(hostObservable)) {
157
+ break;
158
+ }
159
+ hostComplete.wake({ invitation: hostInvitation });
157
160
  break;
158
161
  }
159
- hostComplete.wake({ invitation: hostInvitation });
160
- break;
161
- }
162
162
 
163
- case Invitation.State.CANCELLED: {
164
- if (hooks?.host?.onCancelled?.(hostObservable)) {
163
+ case Invitation.State.CANCELLED: {
164
+ if (hooks?.host?.onCancelled?.(hostObservable)) {
165
+ break;
166
+ }
167
+ hostComplete.wake({ invitation: hostInvitation });
165
168
  break;
166
169
  }
167
- hostComplete.wake({ invitation: hostInvitation });
168
- break;
169
- }
170
170
 
171
- case Invitation.State.TIMEOUT: {
172
- if (hooks?.host?.onTimeout?.(hostObservable)) {
171
+ case Invitation.State.TIMEOUT: {
172
+ if (hooks?.host?.onTimeout?.(hostObservable)) {
173
+ break;
174
+ }
175
+ hostComplete.wake({ invitation: hostInvitation });
173
176
  break;
174
177
  }
175
- hostComplete.wake({ invitation: hostInvitation });
176
- break;
177
178
  }
178
- }
179
- },
180
- (error: Error) => {
181
- if (hooks?.host?.onError?.(hostObservable)) {
182
- return;
183
- }
184
- hostComplete.wake({ error });
185
- },
186
- );
179
+ },
180
+ (error: Error) => {
181
+ if (hooks?.host?.onError?.(hostObservable)) {
182
+ return;
183
+ }
184
+ hostComplete.wake({ error });
185
+ },
186
+ );
187
+ });
187
188
 
188
189
  return [hostComplete.wait(), guestComplete.wait()];
189
190
  };
190
191
 
191
- const createInvitation = (
192
+ const createInvitation = async (
192
193
  host: ServiceContext | InvitationHost,
193
194
  options?: Partial<Invitation>,
194
- ): CancellableInvitation => {
195
+ ): Promise<CancellableInvitation> => {
195
196
  options ??= {
196
197
  authMethod: Invitation.AuthMethod.NONE,
197
198
  ...(options ?? {}),
198
199
  };
199
200
 
200
201
  if (host instanceof ServiceContext) {
201
- const hostHandler = host.getInvitationHandler({ kind: Invitation.Kind.SPACE, ...options });
202
- return host.invitations.createInvitation(hostHandler, options);
202
+ return host.invitationsManager.createInvitation({
203
+ kind: Invitation.Kind.SPACE,
204
+ ...options,
205
+ });
203
206
  }
204
207
 
205
208
  return host.share(options);
@@ -6,15 +6,24 @@ import { type Config } from '@dxos/config';
6
6
  import { Context } from '@dxos/context';
7
7
  import { createCredentialSignerWithChain, CredentialGenerator } from '@dxos/credentials';
8
8
  import { failUndefined } from '@dxos/debug';
9
- import { AutomergeHost, MetadataStore, SnapshotStore, SpaceManager, valueEncoding } from '@dxos/echo-pipeline';
9
+ import {
10
+ AutomergeHost,
11
+ MetadataStore,
12
+ type LevelDB,
13
+ SnapshotStore,
14
+ SpaceManager,
15
+ valueEncoding,
16
+ } from '@dxos/echo-pipeline';
17
+ import { createTestLevel } from '@dxos/echo-pipeline/testing';
10
18
  import { FeedFactory, FeedStore } from '@dxos/feed-store';
11
- import { createTestLevel } from '@dxos/indexing/testing';
12
19
  import { Keyring } from '@dxos/keyring';
13
20
  import { MemorySignalManager, MemorySignalManagerContext } from '@dxos/messaging';
14
21
  import { MemoryTransportFactory, NetworkManager } from '@dxos/network-manager';
22
+ import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
15
23
  import { createStorage, StorageType, type Storage } from '@dxos/random-access-storage';
16
24
  import { BlobStore } from '@dxos/teleport-extension-object-sync';
17
25
 
26
+ import { InvitationsHandler, InvitationsManager, SpaceInvitationProtocol } from '../invitations';
18
27
  import { ClientServicesHost, ServiceContext } from '../services';
19
28
  import { DataSpaceManager, type SigningContext } from '../spaces';
20
29
 
@@ -42,7 +51,8 @@ export const createServiceContext = async ({
42
51
  signalManager,
43
52
  transportFactory: MemoryTransportFactory,
44
53
  });
45
- const level = await createTestLevel();
54
+ const level = createTestLevel();
55
+ await level.open();
46
56
 
47
57
  return new ServiceContext(storage, level, networkManager, signalManager);
48
58
  };
@@ -85,6 +95,7 @@ export type TestPeerOpts = {
85
95
 
86
96
  export type TestPeerProps = {
87
97
  storage?: Storage;
98
+ level?: LevelDB;
88
99
  feedStore?: FeedStore<any>;
89
100
  metadataStore?: MetadataStore;
90
101
  keyring?: Keyring;
@@ -95,6 +106,7 @@ export type TestPeerProps = {
95
106
  signingContext?: SigningContext;
96
107
  blobStore?: BlobStore;
97
108
  automergeHost?: AutomergeHost;
109
+ invitationsManager?: InvitationsManager;
98
110
  };
99
111
 
100
112
  export class TestPeer {
@@ -117,6 +129,10 @@ export class TestPeer {
117
129
  return (this._props.keyring ??= new Keyring(this.storage.createDirectory('keyring')));
118
130
  }
119
131
 
132
+ get level() {
133
+ return (this._props.level ??= createTestLevel());
134
+ }
135
+
120
136
  get feedStore() {
121
137
  return (this._props.feedStore ??= new FeedStore({
122
138
  factory: new FeedFactory({
@@ -163,10 +179,12 @@ export class TestPeer {
163
179
  }
164
180
 
165
181
  get automergeHost() {
166
- return (this._props.automergeHost ??= new AutomergeHost({ directory: this.storage.createDirectory('automerge') }));
182
+ return (this._props.automergeHost ??= new AutomergeHost({
183
+ db: this.level.sublevel('automerge'),
184
+ }));
167
185
  }
168
186
 
169
- get dataSpaceManager() {
187
+ get dataSpaceManager(): DataSpaceManager {
170
188
  return (this._props.dataSpaceManager ??= new DataSpaceManager(
171
189
  this.spaceManager,
172
190
  this.metadataStore,
@@ -174,6 +192,21 @@ export class TestPeer {
174
192
  this.identity,
175
193
  this.feedStore,
176
194
  this.automergeHost,
195
+ this.invitationsManager,
196
+ ));
197
+ }
198
+
199
+ get invitationsManager() {
200
+ return (this._props.invitationsManager ??= new InvitationsManager(
201
+ new InvitationsHandler(this.networkManager),
202
+ (invitation) => {
203
+ if (invitation.kind === Invitation.Kind.SPACE) {
204
+ return new SpaceInvitationProtocol(this.dataSpaceManager, this.identity!, this.keyring, invitation.spaceKey!);
205
+ } else {
206
+ throw new Error('not implemented');
207
+ }
208
+ },
209
+ this.metadataStore,
177
210
  ));
178
211
  }
179
212
 
@@ -182,6 +215,7 @@ export class TestPeer {
182
215
  }
183
216
 
184
217
  async destroy() {
218
+ await this.level.close();
185
219
  await this.storage.reset();
186
220
  }
187
221
  }
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const DXOS_VERSION = "0.4.10-main.fd4f2a3";
1
+ export const DXOS_VERSION = "0.4.10-main.fd8ea31";