@dxos/client-services 0.4.10-main.c75170d → 0.4.10-main.c8e5c39
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/lib/browser/{chunk-JP7F2IH3.mjs → chunk-7OKNHCYB.mjs} +425 -410
- package/dist/lib/browser/chunk-7OKNHCYB.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +6 -4
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/packlets/testing/index.mjs +131 -116
- package/dist/lib/browser/packlets/testing/index.mjs.map +3 -3
- package/dist/lib/node/{chunk-34EZSH65.cjs → chunk-5JA576YH.cjs} +527 -508
- package/dist/lib/node/chunk-5JA576YH.cjs.map +7 -0
- package/dist/lib/node/index.cjs +48 -46
- package/dist/lib/node/index.cjs.map +3 -3
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/packlets/testing/index.cjs +130 -118
- package/dist/lib/node/packlets/testing/index.cjs.map +3 -3
- package/dist/types/src/packlets/identity/identity-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts +3 -1
- package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitation-protocol.d.ts +6 -1
- package/dist/types/src/packlets/invitations/invitation-protocol.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitations-handler.d.ts +4 -2
- package/dist/types/src/packlets/invitations/invitations-handler.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitations-manager.d.ts +9 -7
- package/dist/types/src/packlets/invitations/invitations-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitations-service.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts +2 -1
- package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts.map +1 -1
- package/dist/types/src/packlets/services/service-context.d.ts +4 -6
- package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
- package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/data-space-manager.d.ts +8 -3
- package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/data-space.d.ts +4 -3
- package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
- package/dist/types/src/packlets/storage/level.d.ts.map +1 -1
- package/dist/types/src/packlets/testing/invitation-utils.d.ts.map +1 -1
- package/dist/types/src/packlets/testing/test-builder.d.ts +7 -3
- package/dist/types/src/packlets/testing/test-builder.d.ts.map +1 -1
- package/dist/types/src/packlets/vault/worker-runtime.d.ts.map +1 -1
- package/dist/types/src/version.d.ts +1 -1
- package/package.json +34 -34
- package/src/packlets/identity/identity-manager.ts +1 -0
- package/src/packlets/identity/identity.test.ts +3 -0
- package/src/packlets/invitations/device-invitation-protocol.ts +6 -1
- package/src/packlets/invitations/invitation-protocol.ts +7 -1
- package/src/packlets/invitations/invitations-handler.ts +10 -71
- package/src/packlets/invitations/invitations-manager.ts +114 -40
- package/src/packlets/invitations/invitations-service.ts +4 -2
- package/src/packlets/invitations/space-invitation-protocol.ts +45 -3
- package/src/packlets/services/automerge-host.test.ts +4 -4
- package/src/packlets/services/service-context.test.ts +3 -3
- package/src/packlets/services/service-context.ts +12 -25
- package/src/packlets/services/service-host.test.ts +6 -0
- package/src/packlets/services/service-host.ts +5 -16
- package/src/packlets/spaces/data-space-manager.test.ts +4 -4
- package/src/packlets/spaces/data-space-manager.ts +56 -13
- package/src/packlets/spaces/data-space.ts +14 -19
- package/src/packlets/storage/level.ts +1 -0
- package/src/packlets/testing/invitation-utils.ts +100 -97
- package/src/packlets/testing/test-builder.ts +27 -14
- package/src/packlets/vault/worker-runtime.ts +3 -1
- package/src/version.ts +1 -1
- package/dist/lib/browser/chunk-JP7F2IH3.mjs.map +0 -7
- package/dist/lib/node/chunk-34EZSH65.cjs.map +0 -7
- package/dist/types/src/packlets/indexing/index.d.ts +0 -2
- package/dist/types/src/packlets/indexing/index.d.ts.map +0 -1
- package/dist/types/src/packlets/indexing/util.d.ts +0 -16
- package/dist/types/src/packlets/indexing/util.d.ts.map +0 -1
- package/src/packlets/indexing/index.ts +0 -5
- package/src/packlets/indexing/util.ts +0 -89
|
@@ -4,18 +4,20 @@
|
|
|
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';
|
|
8
|
-
import { type
|
|
7
|
+
import { getCredentialAssertion, type CredentialSigner, type DelegateInvitationCredential } from '@dxos/credentials';
|
|
8
|
+
import { type EchoHost } from '@dxos/echo-db';
|
|
9
|
+
import { type MetadataStore, type Space, type SpaceManager } from '@dxos/echo-pipeline';
|
|
9
10
|
import { type FeedStore } from '@dxos/feed-store';
|
|
10
11
|
import { invariant } from '@dxos/invariant';
|
|
11
12
|
import { type Keyring } from '@dxos/keyring';
|
|
12
13
|
import { PublicKey } from '@dxos/keys';
|
|
13
14
|
import { log } from '@dxos/log';
|
|
14
15
|
import { trace } from '@dxos/protocols';
|
|
15
|
-
import { SpaceState } from '@dxos/protocols/proto/dxos/client/services';
|
|
16
|
+
import { Invitation, SpaceState } from '@dxos/protocols/proto/dxos/client/services';
|
|
16
17
|
import { type FeedMessage } from '@dxos/protocols/proto/dxos/echo/feed';
|
|
17
18
|
import { type SpaceMetadata } from '@dxos/protocols/proto/dxos/echo/metadata';
|
|
18
19
|
import { type Credential, type ProfileDocument } from '@dxos/protocols/proto/dxos/halo/credentials';
|
|
20
|
+
import { type DelegateSpaceInvitation } from '@dxos/protocols/proto/dxos/halo/invitations';
|
|
19
21
|
import { Gossip, Presence } from '@dxos/teleport-extension-gossip';
|
|
20
22
|
import { type Timeframe } from '@dxos/timeframe';
|
|
21
23
|
import { ComplexMap, deferFunction, forEachAsync } from '@dxos/util';
|
|
@@ -23,6 +25,7 @@ import { ComplexMap, deferFunction, forEachAsync } from '@dxos/util';
|
|
|
23
25
|
import { DataSpace } from './data-space';
|
|
24
26
|
import { spaceGenesis } from './genesis';
|
|
25
27
|
import { createAuthProvider } from '../identity';
|
|
28
|
+
import { type InvitationsManager } from '../invitations';
|
|
26
29
|
|
|
27
30
|
const PRESENCE_ANNOUNCE_INTERVAL = 10_000;
|
|
28
31
|
const PRESENCE_OFFLINE_TIMEOUT = 20_000;
|
|
@@ -77,7 +80,8 @@ export class DataSpaceManager {
|
|
|
77
80
|
private readonly _keyring: Keyring,
|
|
78
81
|
private readonly _signingContext: SigningContext,
|
|
79
82
|
private readonly _feedStore: FeedStore<FeedMessage>,
|
|
80
|
-
private readonly
|
|
83
|
+
private readonly _echoHost: EchoHost,
|
|
84
|
+
private readonly _invitationsManager: InvitationsManager,
|
|
81
85
|
params?: DataSpaceManagerRuntimeParams,
|
|
82
86
|
) {
|
|
83
87
|
const {
|
|
@@ -149,14 +153,10 @@ export class DataSpaceManager {
|
|
|
149
153
|
|
|
150
154
|
log('creating space...', { spaceKey });
|
|
151
155
|
|
|
152
|
-
const
|
|
153
|
-
automergeRoot.change((doc: any) => {
|
|
154
|
-
doc.access = { spaceKey: spaceKey.toHex() };
|
|
155
|
-
});
|
|
156
|
-
|
|
156
|
+
const automergeRootUrl = await this._echoHost.createSpaceRoot(spaceKey);
|
|
157
157
|
const space = await this._constructSpace(metadata);
|
|
158
158
|
|
|
159
|
-
const credentials = await spaceGenesis(this._keyring, this._signingContext, space.inner,
|
|
159
|
+
const credentials = await spaceGenesis(this._keyring, this._signingContext, space.inner, automergeRootUrl);
|
|
160
160
|
await this._metadataStore.addSpace(metadata);
|
|
161
161
|
|
|
162
162
|
const memberCredential = credentials[1];
|
|
@@ -240,13 +240,16 @@ export class DataSpaceManager {
|
|
|
240
240
|
gossip.createExtension({ remotePeerId: session.remotePeerId }),
|
|
241
241
|
);
|
|
242
242
|
session.addExtension('dxos.mesh.teleport.notarization', dataSpace.notarizationPlugin.createExtension());
|
|
243
|
-
this.
|
|
244
|
-
session.addExtension('dxos.mesh.teleport.automerge', this.
|
|
243
|
+
this._echoHost.authorizeDevice(space.key, session.remotePeerId);
|
|
244
|
+
session.addExtension('dxos.mesh.teleport.automerge', this._echoHost.createReplicationExtension());
|
|
245
245
|
},
|
|
246
246
|
onAuthFailure: () => {
|
|
247
247
|
log.warn('auth failure');
|
|
248
248
|
},
|
|
249
249
|
memberKey: this._signingContext.identityKey,
|
|
250
|
+
onDelegatedInvitationStatusChange: (invitation, isActive) => {
|
|
251
|
+
return this._handleInvitationStatusChange(dataSpace, invitation, isActive);
|
|
252
|
+
},
|
|
250
253
|
});
|
|
251
254
|
controlFeed && (await space.setControlFeed(controlFeed));
|
|
252
255
|
dataFeed && (await space.setDataFeed(dataFeed));
|
|
@@ -259,6 +262,7 @@ export class DataSpaceManager {
|
|
|
259
262
|
presence,
|
|
260
263
|
keyring: this._keyring,
|
|
261
264
|
feedStore: this._feedStore,
|
|
265
|
+
echoHost: this._echoHost,
|
|
262
266
|
signingContext: this._signingContext,
|
|
263
267
|
callbacks: {
|
|
264
268
|
beforeReady: async () => {
|
|
@@ -267,6 +271,7 @@ export class DataSpaceManager {
|
|
|
267
271
|
afterReady: async () => {
|
|
268
272
|
log('after space ready', { space: space.key, open: this._isOpen });
|
|
269
273
|
if (this._isOpen) {
|
|
274
|
+
await this._createDelegatedInvitations(dataSpace, [...space.spaceState.invitations.entries()]);
|
|
270
275
|
this.updated.emit();
|
|
271
276
|
}
|
|
272
277
|
},
|
|
@@ -275,7 +280,6 @@ export class DataSpaceManager {
|
|
|
275
280
|
},
|
|
276
281
|
},
|
|
277
282
|
cache: metadata.cache,
|
|
278
|
-
automergeHost: this._automergeHost,
|
|
279
283
|
});
|
|
280
284
|
|
|
281
285
|
if (metadata.state !== SpaceState.INACTIVE) {
|
|
@@ -289,4 +293,43 @@ export class DataSpaceManager {
|
|
|
289
293
|
this._spaces.set(metadata.key, dataSpace);
|
|
290
294
|
return dataSpace;
|
|
291
295
|
}
|
|
296
|
+
|
|
297
|
+
private async _handleInvitationStatusChange(
|
|
298
|
+
dataSpace: DataSpace | undefined,
|
|
299
|
+
delegatedInvitation: DelegateInvitationCredential,
|
|
300
|
+
isActive: boolean,
|
|
301
|
+
): Promise<void> {
|
|
302
|
+
if (dataSpace?.state !== SpaceState.READY) {
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
if (isActive) {
|
|
306
|
+
await this._createDelegatedInvitations(dataSpace, [
|
|
307
|
+
[delegatedInvitation.credentialId, delegatedInvitation.invitation],
|
|
308
|
+
]);
|
|
309
|
+
} else {
|
|
310
|
+
await this._invitationsManager.cancelInvitation(delegatedInvitation.invitation);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
private async _createDelegatedInvitations(
|
|
315
|
+
space: DataSpace,
|
|
316
|
+
invitations: Array<[PublicKey, DelegateSpaceInvitation]>,
|
|
317
|
+
): Promise<void> {
|
|
318
|
+
const tasks = invitations.map(([credentialId, invitation]) => {
|
|
319
|
+
return this._invitationsManager.createInvitation({
|
|
320
|
+
type: Invitation.Type.DELEGATED,
|
|
321
|
+
kind: Invitation.Kind.SPACE,
|
|
322
|
+
spaceKey: space.key,
|
|
323
|
+
authMethod: invitation.authMethod,
|
|
324
|
+
invitationId: invitation.invitationId,
|
|
325
|
+
swarmKey: invitation.swarmKey,
|
|
326
|
+
guestKeypair: invitation.guestKey ? { publicKey: invitation.guestKey } : undefined,
|
|
327
|
+
lifetime: invitation.expiresOn ? invitation.expiresOn.getTime() - Date.now() : undefined,
|
|
328
|
+
multiUse: invitation.multiUse,
|
|
329
|
+
delegationCredentialId: credentialId,
|
|
330
|
+
persistent: false,
|
|
331
|
+
});
|
|
332
|
+
});
|
|
333
|
+
await Promise.all(tasks);
|
|
334
|
+
}
|
|
292
335
|
}
|
|
@@ -6,15 +6,10 @@ 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 {
|
|
10
|
-
import {
|
|
11
|
-
type MetadataStore,
|
|
12
|
-
type Space,
|
|
13
|
-
createMappedFeedWriter,
|
|
14
|
-
type AutomergeHost,
|
|
15
|
-
type SpaceDoc,
|
|
16
|
-
} from '@dxos/echo-pipeline';
|
|
9
|
+
import { type EchoHost } from '@dxos/echo-db';
|
|
10
|
+
import { type MetadataStore, type Space, createMappedFeedWriter, type SpaceDoc } from '@dxos/echo-pipeline';
|
|
17
11
|
import { AutomergeDocumentLoaderImpl } from '@dxos/echo-pipeline';
|
|
12
|
+
import { TYPE_PROPERTIES } from '@dxos/echo-schema';
|
|
18
13
|
import { type FeedStore } from '@dxos/feed-store';
|
|
19
14
|
import { failedInvariant, invariant } from '@dxos/invariant';
|
|
20
15
|
import { type Keyring } from '@dxos/keyring';
|
|
@@ -66,10 +61,10 @@ export type DataSpaceParams = {
|
|
|
66
61
|
presence: Presence;
|
|
67
62
|
keyring: Keyring;
|
|
68
63
|
feedStore: FeedStore<FeedMessage>;
|
|
64
|
+
echoHost: EchoHost;
|
|
69
65
|
signingContext: SigningContext;
|
|
70
66
|
callbacks?: DataSpaceCallbacks;
|
|
71
67
|
cache?: SpaceCache;
|
|
72
|
-
automergeHost: AutomergeHost;
|
|
73
68
|
};
|
|
74
69
|
|
|
75
70
|
export type CreateEpochOptions = {
|
|
@@ -92,7 +87,7 @@ export class DataSpace {
|
|
|
92
87
|
private readonly _notarizationPlugin = new NotarizationPlugin();
|
|
93
88
|
private readonly _callbacks: DataSpaceCallbacks;
|
|
94
89
|
private readonly _cache?: SpaceCache = undefined;
|
|
95
|
-
private readonly
|
|
90
|
+
private readonly _echoHost: EchoHost;
|
|
96
91
|
|
|
97
92
|
// TODO(dmaretskyi): Move into Space?
|
|
98
93
|
private readonly _automergeSpaceState = new AutomergeSpaceState((rootUrl) => this._onNewAutomergeRoot(rootUrl));
|
|
@@ -120,7 +115,7 @@ export class DataSpace {
|
|
|
120
115
|
this._metadataStore = params.metadataStore;
|
|
121
116
|
this._signingContext = params.signingContext;
|
|
122
117
|
this._callbacks = params.callbacks ?? {};
|
|
123
|
-
this.
|
|
118
|
+
this._echoHost = params.echoHost;
|
|
124
119
|
|
|
125
120
|
this.authVerifier = new TrustedKeySetAuthVerifier({
|
|
126
121
|
trustedKeysProvider: () =>
|
|
@@ -363,8 +358,8 @@ export class DataSpace {
|
|
|
363
358
|
|
|
364
359
|
private _onNewAutomergeRoot(rootUrl: string) {
|
|
365
360
|
log('loading automerge root doc for space', { space: this.key, rootUrl });
|
|
366
|
-
this.
|
|
367
|
-
const handle = this.
|
|
361
|
+
this._echoHost.replicateDocument(rootUrl);
|
|
362
|
+
const handle = this._echoHost.automergeRepo.find(rootUrl as any);
|
|
368
363
|
|
|
369
364
|
queueMicrotask(async () => {
|
|
370
365
|
try {
|
|
@@ -419,7 +414,7 @@ export class DataSpace {
|
|
|
419
414
|
break;
|
|
420
415
|
case CreateEpochRequest.Migration.INIT_AUTOMERGE:
|
|
421
416
|
{
|
|
422
|
-
const document = this.
|
|
417
|
+
const document = this._echoHost.automergeRepo.create();
|
|
423
418
|
// TODO(dmaretskyi): Unify epoch construction.
|
|
424
419
|
epoch = {
|
|
425
420
|
previousId: this._automergeSpaceState.lastEpoch?.id,
|
|
@@ -432,9 +427,9 @@ export class DataSpace {
|
|
|
432
427
|
case CreateEpochRequest.Migration.PRUNE_AUTOMERGE_ROOT_HISTORY:
|
|
433
428
|
{
|
|
434
429
|
const currentRootUrl = this._automergeSpaceState.rootUrl;
|
|
435
|
-
const rootHandle = this.
|
|
430
|
+
const rootHandle = this._echoHost.automergeRepo.find(currentRootUrl as any);
|
|
436
431
|
await cancelWithContext(this._ctx, asyncTimeout(rootHandle.whenReady(), 10_000));
|
|
437
|
-
const newRoot = this.
|
|
432
|
+
const newRoot = this._echoHost.automergeRepo.create(rootHandle.docSync());
|
|
438
433
|
invariant(typeof newRoot.url === 'string' && newRoot.url.length > 0);
|
|
439
434
|
// TODO(dmaretskyi): Unify epoch construction.
|
|
440
435
|
epoch = {
|
|
@@ -450,7 +445,7 @@ export class DataSpace {
|
|
|
450
445
|
log.info('Fragmenting');
|
|
451
446
|
|
|
452
447
|
const currentRootUrl = this._automergeSpaceState.rootUrl;
|
|
453
|
-
const rootHandle = this.
|
|
448
|
+
const rootHandle = this._echoHost.automergeRepo.find<SpaceDoc>(currentRootUrl as any);
|
|
454
449
|
await cancelWithContext(this._ctx, asyncTimeout(rootHandle.whenReady(), 10_000));
|
|
455
450
|
|
|
456
451
|
// Find properties object.
|
|
@@ -461,11 +456,11 @@ export class DataSpace {
|
|
|
461
456
|
|
|
462
457
|
// Create a new space doc with the properties object.
|
|
463
458
|
const newSpaceDoc: SpaceDoc = { ...rootHandle.docSync(), objects: Object.fromEntries([properties]) };
|
|
464
|
-
const newRoot = this.
|
|
459
|
+
const newRoot = this._echoHost.automergeRepo.create(newSpaceDoc);
|
|
465
460
|
invariant(typeof newRoot.url === 'string' && newRoot.url.length > 0);
|
|
466
461
|
|
|
467
462
|
// Create new automerge documents for all objects.
|
|
468
|
-
const docLoader = new AutomergeDocumentLoaderImpl(this.key, this.
|
|
463
|
+
const docLoader = new AutomergeDocumentLoaderImpl(this.key, this._echoHost.automergeRepo);
|
|
469
464
|
await docLoader.loadSpaceRootDocHandle(this._ctx, { rootUrl: newRoot.url });
|
|
470
465
|
|
|
471
466
|
otherObjects.forEach(([key, value]) => {
|
|
@@ -14,6 +14,7 @@ export const createLevel = async (config: Runtime.Client.Storage) => {
|
|
|
14
14
|
const persistent = isPersistent(config);
|
|
15
15
|
const storagePath = persistent ? path.join(getRootPath(config), 'level') : `/tmp/dxos-${PublicKey.random().toHex()}`;
|
|
16
16
|
const level = new Level<string, string>(storagePath);
|
|
17
|
+
// TODO(dmaretskyi): This function shouldn't call open - .
|
|
17
18
|
await level.open();
|
|
18
19
|
return level;
|
|
19
20
|
};
|
|
@@ -60,146 +60,149 @@ export const performInvitation = ({
|
|
|
60
60
|
const guestComplete = new Trigger<Result>();
|
|
61
61
|
const authCode = new Trigger<string>();
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
83
|
+
case Invitation.State.CONNECTED: {
|
|
84
|
+
hooks?.guest?.onConnected?.(guestObservable);
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
87
|
|
|
88
|
-
|
|
89
|
-
|
|
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
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
96
|
+
case Invitation.State.AUTHENTICATING: {
|
|
97
|
+
hooks?.guest?.onAuthenticating?.(guestObservable);
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
100
|
|
|
101
|
-
|
|
102
|
-
|
|
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
|
-
|
|
110
|
-
|
|
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
|
-
|
|
118
|
-
|
|
119
|
-
|
|
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
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
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
|
-
|
|
141
|
-
|
|
135
|
+
case Invitation.State.CONNECTED: {
|
|
136
|
+
hooks?.host?.onConnected?.(hostObservable);
|
|
142
137
|
break;
|
|
143
138
|
}
|
|
144
|
-
|
|
145
|
-
|
|
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
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
150
|
+
case Invitation.State.AUTHENTICATING: {
|
|
151
|
+
hooks?.host?.onAuthenticating?.(hostObservable);
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
154
|
|
|
155
|
-
|
|
156
|
-
|
|
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
|
-
|
|
164
|
-
|
|
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
|
-
|
|
172
|
-
|
|
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
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
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
|
-
|
|
202
|
-
|
|
202
|
+
return host.invitationsManager.createInvitation({
|
|
203
|
+
kind: Invitation.Kind.SPACE,
|
|
204
|
+
...options,
|
|
205
|
+
});
|
|
203
206
|
}
|
|
204
207
|
|
|
205
208
|
return host.share(options);
|
|
@@ -6,22 +6,18 @@ 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 {
|
|
10
|
-
|
|
11
|
-
MetadataStore,
|
|
12
|
-
type LevelDB,
|
|
13
|
-
SnapshotStore,
|
|
14
|
-
SpaceManager,
|
|
15
|
-
valueEncoding,
|
|
16
|
-
} from '@dxos/echo-pipeline';
|
|
9
|
+
import { EchoHost } from '@dxos/echo-db';
|
|
10
|
+
import { MetadataStore, type LevelDB, SnapshotStore, SpaceManager, valueEncoding } from '@dxos/echo-pipeline';
|
|
17
11
|
import { createTestLevel } from '@dxos/echo-pipeline/testing';
|
|
18
12
|
import { FeedFactory, FeedStore } from '@dxos/feed-store';
|
|
19
13
|
import { Keyring } from '@dxos/keyring';
|
|
20
14
|
import { MemorySignalManager, MemorySignalManagerContext } from '@dxos/messaging';
|
|
21
15
|
import { MemoryTransportFactory, NetworkManager } from '@dxos/network-manager';
|
|
16
|
+
import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
|
|
22
17
|
import { createStorage, StorageType, type Storage } from '@dxos/random-access-storage';
|
|
23
18
|
import { BlobStore } from '@dxos/teleport-extension-object-sync';
|
|
24
19
|
|
|
20
|
+
import { InvitationsHandler, InvitationsManager, SpaceInvitationProtocol } from '../invitations';
|
|
25
21
|
import { ClientServicesHost, ServiceContext } from '../services';
|
|
26
22
|
import { DataSpaceManager, type SigningContext } from '../spaces';
|
|
27
23
|
|
|
@@ -103,7 +99,8 @@ export type TestPeerProps = {
|
|
|
103
99
|
snapshotStore?: SnapshotStore;
|
|
104
100
|
signingContext?: SigningContext;
|
|
105
101
|
blobStore?: BlobStore;
|
|
106
|
-
|
|
102
|
+
echoHost?: EchoHost;
|
|
103
|
+
invitationsManager?: InvitationsManager;
|
|
107
104
|
};
|
|
108
105
|
|
|
109
106
|
export class TestPeer {
|
|
@@ -175,20 +172,36 @@ export class TestPeer {
|
|
|
175
172
|
return this._props.signingContext ?? failUndefined();
|
|
176
173
|
}
|
|
177
174
|
|
|
178
|
-
get
|
|
179
|
-
return (this._props.
|
|
180
|
-
|
|
175
|
+
get echoHost() {
|
|
176
|
+
return (this._props.echoHost ??= new EchoHost({
|
|
177
|
+
kv: this.level,
|
|
178
|
+
storage: this.storage,
|
|
181
179
|
}));
|
|
182
180
|
}
|
|
183
181
|
|
|
184
|
-
get dataSpaceManager() {
|
|
182
|
+
get dataSpaceManager(): DataSpaceManager {
|
|
185
183
|
return (this._props.dataSpaceManager ??= new DataSpaceManager(
|
|
186
184
|
this.spaceManager,
|
|
187
185
|
this.metadataStore,
|
|
188
186
|
this.keyring,
|
|
189
187
|
this.identity,
|
|
190
188
|
this.feedStore,
|
|
191
|
-
this.
|
|
189
|
+
this.echoHost,
|
|
190
|
+
this.invitationsManager,
|
|
191
|
+
));
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
get invitationsManager() {
|
|
195
|
+
return (this._props.invitationsManager ??= new InvitationsManager(
|
|
196
|
+
new InvitationsHandler(this.networkManager),
|
|
197
|
+
(invitation) => {
|
|
198
|
+
if (invitation.kind === Invitation.Kind.SPACE) {
|
|
199
|
+
return new SpaceInvitationProtocol(this.dataSpaceManager, this.identity!, this.keyring, invitation.spaceKey!);
|
|
200
|
+
} else {
|
|
201
|
+
throw new Error('not implemented');
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
this.metadataStore,
|
|
192
205
|
));
|
|
193
206
|
}
|
|
194
207
|
|
|
@@ -120,7 +120,9 @@ export class WorkerRuntime {
|
|
|
120
120
|
this._sessions.delete(session);
|
|
121
121
|
if (this._sessions.size === 0) {
|
|
122
122
|
// Terminate the worker when all sessions are closed.
|
|
123
|
-
self
|
|
123
|
+
if (globalThis.self) {
|
|
124
|
+
self.close();
|
|
125
|
+
}
|
|
124
126
|
} else {
|
|
125
127
|
this._reconnectWebrtc();
|
|
126
128
|
}
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const DXOS_VERSION = "0.4.10-main.
|
|
1
|
+
export const DXOS_VERSION = "0.4.10-main.c8e5c39";
|