@dxos/client-services 0.5.9-main.bdf733d → 0.5.9-main.bf3bb8f
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-KNGR7BYM.mjs → chunk-IUSAD4RP.mjs} +1678 -935
- package/dist/lib/browser/chunk-IUSAD4RP.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +13 -4
- package/dist/lib/browser/index.mjs.map +1 -1
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/packlets/testing/index.mjs +20 -13
- package/dist/lib/browser/packlets/testing/index.mjs.map +3 -3
- package/dist/lib/node/{chunk-WWHTBQNR.cjs → chunk-5PALJZPW.cjs} +1936 -1200
- package/dist/lib/node/chunk-5PALJZPW.cjs.map +7 -0
- package/dist/lib/node/index.cjs +53 -44
- package/dist/lib/node/index.cjs.map +1 -1
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/packlets/testing/index.cjs +26 -19
- package/dist/lib/node/packlets/testing/index.cjs.map +3 -3
- package/dist/types/src/packlets/identity/contacts-service.d.ts +14 -0
- package/dist/types/src/packlets/identity/contacts-service.d.ts.map +1 -0
- package/dist/types/src/packlets/identity/default-space-state-machine.d.ts +19 -0
- package/dist/types/src/packlets/identity/default-space-state-machine.d.ts.map +1 -0
- package/dist/types/src/packlets/identity/identity-service.d.ts +14 -7
- package/dist/types/src/packlets/identity/identity-service.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity.d.ts +4 -1
- package/dist/types/src/packlets/identity/identity.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitations-handler.d.ts.map +1 -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.map +1 -1
- package/dist/types/src/packlets/services/service-host.d.ts +1 -1
- package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/automerge-space-state.d.ts +4 -1
- package/dist/types/src/packlets/spaces/automerge-space-state.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/data-space-manager.d.ts +15 -4
- package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/data-space.d.ts +10 -9
- package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/epoch-migrations.d.ts +23 -0
- package/dist/types/src/packlets/spaces/epoch-migrations.d.ts.map +1 -0
- package/dist/types/src/packlets/spaces/spaces-service.d.ts +5 -2
- package/dist/types/src/packlets/spaces/spaces-service.d.ts.map +1 -1
- package/dist/types/src/packlets/storage/index.d.ts +1 -0
- package/dist/types/src/packlets/storage/index.d.ts.map +1 -1
- package/dist/types/src/packlets/storage/profile-archive.d.ts +14 -0
- package/dist/types/src/packlets/storage/profile-archive.d.ts.map +1 -0
- package/dist/types/src/packlets/testing/test-builder.d.ts +8 -6
- package/dist/types/src/packlets/testing/test-builder.d.ts.map +1 -1
- package/dist/types/src/version.d.ts +1 -1
- package/package.json +36 -36
- package/src/packlets/identity/contacts-service.ts +85 -0
- package/src/packlets/identity/default-space-state-machine.ts +44 -0
- package/src/packlets/identity/identity-service.test.ts +35 -5
- package/src/packlets/identity/identity-service.ts +82 -8
- package/src/packlets/identity/identity.ts +25 -2
- package/src/packlets/invitations/invitations-handler.ts +13 -5
- package/src/packlets/invitations/space-invitation-protocol.ts +11 -32
- package/src/packlets/services/service-context.ts +1 -4
- package/src/packlets/services/service-host.ts +23 -42
- package/src/packlets/spaces/automerge-space-state.ts +11 -2
- package/src/packlets/spaces/data-space-manager.test.ts +46 -1
- package/src/packlets/spaces/data-space-manager.ts +136 -33
- package/src/packlets/spaces/data-space.ts +89 -140
- package/src/packlets/spaces/epoch-migrations.ts +154 -0
- package/src/packlets/spaces/spaces-service.ts +56 -4
- package/src/packlets/storage/index.ts +1 -0
- package/src/packlets/storage/profile-archive.ts +111 -0
- package/src/packlets/testing/test-builder.ts +12 -10
- package/src/version.ts +1 -1
- package/dist/lib/browser/chunk-KNGR7BYM.mjs.map +0 -7
- package/dist/lib/node/chunk-WWHTBQNR.cjs.map +0 -7
|
@@ -16,7 +16,7 @@ import { type Signer } from '@dxos/crypto';
|
|
|
16
16
|
import { type Space } from '@dxos/echo-pipeline';
|
|
17
17
|
import { writeMessages } from '@dxos/feed-store';
|
|
18
18
|
import { invariant } from '@dxos/invariant';
|
|
19
|
-
import { PublicKey } from '@dxos/keys';
|
|
19
|
+
import { PublicKey, type SpaceId } from '@dxos/keys';
|
|
20
20
|
import { log } from '@dxos/log';
|
|
21
21
|
import { type FeedMessage } from '@dxos/protocols/proto/dxos/echo/feed';
|
|
22
22
|
import {
|
|
@@ -26,10 +26,12 @@ import {
|
|
|
26
26
|
} from '@dxos/protocols/proto/dxos/halo/credentials';
|
|
27
27
|
import { type DeviceAdmissionRequest } from '@dxos/protocols/proto/dxos/halo/invitations';
|
|
28
28
|
import { type Presence } from '@dxos/teleport-extension-gossip';
|
|
29
|
+
import { Timeframe } from '@dxos/timeframe';
|
|
29
30
|
import { trace } from '@dxos/tracing';
|
|
30
31
|
import { type ComplexMap, ComplexSet } from '@dxos/util';
|
|
31
32
|
|
|
32
33
|
import { TrustedKeySetAuthVerifier } from './authenticator';
|
|
34
|
+
import { DefaultSpaceStateMachine } from './default-space-state-machine';
|
|
33
35
|
|
|
34
36
|
export type IdentityParams = {
|
|
35
37
|
identityKey: PublicKey;
|
|
@@ -49,6 +51,7 @@ export class Identity {
|
|
|
49
51
|
private readonly _presence?: Presence;
|
|
50
52
|
private readonly _deviceStateMachine: DeviceStateMachine;
|
|
51
53
|
private readonly _profileStateMachine: ProfileStateMachine;
|
|
54
|
+
private readonly _defaultSpaceStateMachine: DefaultSpaceStateMachine;
|
|
52
55
|
public readonly authVerifier: TrustedKeySetAuthVerifier;
|
|
53
56
|
|
|
54
57
|
public readonly identityKey: PublicKey;
|
|
@@ -75,6 +78,10 @@ export class Identity {
|
|
|
75
78
|
identityKey: this.identityKey,
|
|
76
79
|
onUpdate: () => this.stateUpdate.emit(),
|
|
77
80
|
});
|
|
81
|
+
this._defaultSpaceStateMachine = new DefaultSpaceStateMachine({
|
|
82
|
+
identityKey: this.identityKey,
|
|
83
|
+
onUpdate: () => this.stateUpdate.emit(),
|
|
84
|
+
});
|
|
78
85
|
|
|
79
86
|
this.authVerifier = new TrustedKeySetAuthVerifier({
|
|
80
87
|
trustedKeysProvider: () => new ComplexSet(PublicKey.hash, this.authorizedDeviceKeys.keys()),
|
|
@@ -88,17 +95,24 @@ export class Identity {
|
|
|
88
95
|
return this._deviceStateMachine.authorizedDeviceKeys;
|
|
89
96
|
}
|
|
90
97
|
|
|
98
|
+
get defaultSpaceId(): SpaceId | undefined {
|
|
99
|
+
return this._defaultSpaceStateMachine.spaceId;
|
|
100
|
+
}
|
|
101
|
+
|
|
91
102
|
@trace.span()
|
|
92
103
|
async open(ctx: Context) {
|
|
104
|
+
await this._presence?.open();
|
|
93
105
|
await this.space.spaceState.addCredentialProcessor(this._deviceStateMachine);
|
|
94
106
|
await this.space.spaceState.addCredentialProcessor(this._profileStateMachine);
|
|
107
|
+
await this.space.spaceState.addCredentialProcessor(this._defaultSpaceStateMachine);
|
|
95
108
|
await this.space.open(ctx);
|
|
96
109
|
}
|
|
97
110
|
|
|
98
111
|
@trace.span()
|
|
99
112
|
async close(ctx: Context) {
|
|
100
|
-
await this._presence?.
|
|
113
|
+
await this._presence?.close();
|
|
101
114
|
await this.authVerifier.close();
|
|
115
|
+
await this.space.spaceState.removeCredentialProcessor(this._defaultSpaceStateMachine);
|
|
102
116
|
await this.space.spaceState.removeCredentialProcessor(this._profileStateMachine);
|
|
103
117
|
await this.space.spaceState.removeCredentialProcessor(this._deviceStateMachine);
|
|
104
118
|
await this.space.close();
|
|
@@ -157,6 +171,15 @@ export class Identity {
|
|
|
157
171
|
return createCredentialSignerWithKey(this._signer, this.deviceKey);
|
|
158
172
|
}
|
|
159
173
|
|
|
174
|
+
async updateDefaultSpace(spaceId: SpaceId) {
|
|
175
|
+
const credential = await this.getDeviceCredentialSigner().createCredential({
|
|
176
|
+
subject: this.identityKey,
|
|
177
|
+
assertion: { '@type': 'dxos.halo.credentials.DefaultSpace', spaceId },
|
|
178
|
+
});
|
|
179
|
+
const receipt = await this.controlPipeline.writer.write({ credential: { credential } });
|
|
180
|
+
await this.controlPipeline.state.waitUntilTimeframe(new Timeframe([[receipt.feedKey, receipt.seq]]));
|
|
181
|
+
}
|
|
182
|
+
|
|
160
183
|
async admitDevice({ deviceKey, controlFeedKey, dataFeedKey }: DeviceAdmissionRequest) {
|
|
161
184
|
log('Admitting device:', {
|
|
162
185
|
identityKey: this.identityKey,
|
|
@@ -435,11 +435,19 @@ export class InvitationsHandler {
|
|
|
435
435
|
}
|
|
436
436
|
|
|
437
437
|
private _logStateUpdate(invitation: Invitation, actor: any, newState: Invitation.State) {
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
438
|
+
if (this._isNotTerminal(newState)) {
|
|
439
|
+
log('invitation state update', {
|
|
440
|
+
actor: actor?.constructor.name,
|
|
441
|
+
newState: stateToString(newState),
|
|
442
|
+
oldState: stateToString(invitation.state),
|
|
443
|
+
});
|
|
444
|
+
} else {
|
|
445
|
+
log.info('invitation state update', {
|
|
446
|
+
actor: actor?.constructor.name,
|
|
447
|
+
newState: stateToString(newState),
|
|
448
|
+
oldState: stateToString(invitation.state),
|
|
449
|
+
});
|
|
450
|
+
}
|
|
443
451
|
}
|
|
444
452
|
|
|
445
453
|
private _isNotTerminal(currentState: Invitation.State): boolean {
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import {
|
|
6
|
-
createAdmissionCredentials,
|
|
7
6
|
createCancelDelegatedSpaceInvitationCredential,
|
|
8
7
|
createDelegatedSpaceInvitationCredential,
|
|
9
8
|
getCredentialAssertion,
|
|
@@ -21,7 +20,6 @@ import {
|
|
|
21
20
|
SpaceNotFoundError,
|
|
22
21
|
} from '@dxos/protocols';
|
|
23
22
|
import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
|
|
24
|
-
import { type FeedMessage } from '@dxos/protocols/proto/dxos/echo/feed';
|
|
25
23
|
import { SpaceMember, type ProfileDocument } from '@dxos/protocols/proto/dxos/halo/credentials';
|
|
26
24
|
import {
|
|
27
25
|
type AdmissionRequest,
|
|
@@ -73,41 +71,22 @@ export class SpaceInvitationProtocol implements InvitationProtocol {
|
|
|
73
71
|
request: AdmissionRequest,
|
|
74
72
|
guestProfile?: ProfileDocument | undefined,
|
|
75
73
|
): Promise<AdmissionResponse> {
|
|
76
|
-
invariant(this._spaceKey);
|
|
77
|
-
|
|
78
|
-
invariant(space);
|
|
79
|
-
|
|
80
|
-
invariant(request.space);
|
|
81
|
-
const { identityKey, deviceKey } = request.space;
|
|
74
|
+
invariant(this._spaceKey && request.space);
|
|
75
|
+
log('writing guest credentials', { host: this._signingContext.deviceKey, guest: request.space.deviceKey });
|
|
82
76
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
this._signingContext.credentialSigner,
|
|
91
|
-
identityKey,
|
|
92
|
-
space.key,
|
|
93
|
-
space.inner.genesisFeedKey,
|
|
94
|
-
invitation.role ?? SpaceMember.Role.ADMIN,
|
|
95
|
-
space.inner.spaceState.membershipChainHeads,
|
|
96
|
-
guestProfile,
|
|
97
|
-
invitation.delegationCredentialId,
|
|
98
|
-
);
|
|
99
|
-
|
|
100
|
-
// TODO(dmaretskyi): Refactor.
|
|
101
|
-
invariant(credentials[0].credential);
|
|
102
|
-
const spaceMemberCredential = credentials[0].credential.credential;
|
|
103
|
-
invariant(getCredentialAssertion(spaceMemberCredential)['@type'] === 'dxos.halo.credentials.SpaceMember');
|
|
104
|
-
|
|
105
|
-
await writeMessages(space.inner.controlPipeline.writer, credentials);
|
|
77
|
+
const spaceMemberCredential = await this._spaceManager.admitMember({
|
|
78
|
+
spaceKey: this._spaceKey,
|
|
79
|
+
identityKey: request.space.identityKey,
|
|
80
|
+
role: invitation.role ?? SpaceMember.Role.ADMIN,
|
|
81
|
+
profile: guestProfile,
|
|
82
|
+
delegationCredentialId: invitation.delegationCredentialId,
|
|
83
|
+
});
|
|
106
84
|
|
|
85
|
+
const space = this._spaceManager.spaces.get(this._spaceKey);
|
|
107
86
|
return {
|
|
108
87
|
space: {
|
|
109
88
|
credential: spaceMemberCredential,
|
|
110
|
-
controlTimeframe: space
|
|
89
|
+
controlTimeframe: space?.inner.controlPipeline.state.timeframe,
|
|
111
90
|
},
|
|
112
91
|
};
|
|
113
92
|
}
|
|
@@ -120,10 +120,7 @@ export class ServiceContext extends Resource {
|
|
|
120
120
|
this._runtimeParams as IdentityManagerRuntimeParams,
|
|
121
121
|
);
|
|
122
122
|
|
|
123
|
-
this.echoHost = new EchoHost({
|
|
124
|
-
kv: this.level,
|
|
125
|
-
storage: this.storage,
|
|
126
|
-
});
|
|
123
|
+
this.echoHost = new EchoHost({ kv: this.level });
|
|
127
124
|
|
|
128
125
|
this.invitations = new InvitationsHandler(this.networkManager, _runtimeParams?.invitationConnectionDefaultParams);
|
|
129
126
|
this.invitationsManager = new InvitationsManager(
|
|
@@ -3,11 +3,9 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { Event, synchronized } from '@dxos/async';
|
|
6
|
-
import { clientServiceBundle,
|
|
6
|
+
import { clientServiceBundle, type ClientServices } from '@dxos/client-protocol';
|
|
7
7
|
import { type Config } from '@dxos/config';
|
|
8
8
|
import { Context } from '@dxos/context';
|
|
9
|
-
import { type ObjectStructure, encodeReference, type SpaceDoc } from '@dxos/echo-protocol';
|
|
10
|
-
import { getTypeReference } from '@dxos/echo-schema';
|
|
11
9
|
import { invariant } from '@dxos/invariant';
|
|
12
10
|
import { PublicKey } from '@dxos/keys';
|
|
13
11
|
import { type LevelDB } from '@dxos/kv-store';
|
|
@@ -18,7 +16,6 @@ import { trace } from '@dxos/protocols';
|
|
|
18
16
|
import { SystemStatus } from '@dxos/protocols/proto/dxos/client/services';
|
|
19
17
|
import { type Storage } from '@dxos/random-access-storage';
|
|
20
18
|
import { TRACE_PROCESSOR, trace as Trace } from '@dxos/tracing';
|
|
21
|
-
import { assignDeep } from '@dxos/util';
|
|
22
19
|
import { WebsocketRpcClient } from '@dxos/websocket-rpc';
|
|
23
20
|
|
|
24
21
|
import { ServiceContext, type ServiceContextRuntimeParams } from './service-context';
|
|
@@ -31,6 +28,7 @@ import {
|
|
|
31
28
|
createDiagnostics,
|
|
32
29
|
} from '../diagnostics';
|
|
33
30
|
import { IdentityServiceImpl, type CreateIdentityOptions } from '../identity';
|
|
31
|
+
import { ContactsServiceImpl } from '../identity/contacts-service';
|
|
34
32
|
import { InvitationsServiceImpl } from '../invitations';
|
|
35
33
|
import { Lock, type ResourceLock } from '../locks';
|
|
36
34
|
import { LoggingServiceImpl } from '../logging';
|
|
@@ -86,7 +84,7 @@ export class ClientServicesHost {
|
|
|
86
84
|
private _devtoolsProxy?: WebsocketRpcClient<{}, ClientServices>;
|
|
87
85
|
|
|
88
86
|
private _serviceContext!: ServiceContext;
|
|
89
|
-
private readonly _runtimeParams
|
|
87
|
+
private readonly _runtimeParams: ServiceContextRuntimeParams;
|
|
90
88
|
private diagnosticsBroadcastHandler: CollectDiagnosticsBroadcastHandler;
|
|
91
89
|
|
|
92
90
|
@Trace.info()
|
|
@@ -109,7 +107,7 @@ export class ClientServicesHost {
|
|
|
109
107
|
this._storage = storage;
|
|
110
108
|
this._level = level;
|
|
111
109
|
this._callbacks = callbacks;
|
|
112
|
-
this._runtimeParams = runtimeParams;
|
|
110
|
+
this._runtimeParams = runtimeParams ?? {};
|
|
113
111
|
|
|
114
112
|
if (config) {
|
|
115
113
|
this.initialize({ config, transportFactory, signalManager });
|
|
@@ -254,14 +252,26 @@ export class ClientServicesHost {
|
|
|
254
252
|
this._runtimeParams,
|
|
255
253
|
);
|
|
256
254
|
|
|
255
|
+
const dataSpaceManagerProvider = async () => {
|
|
256
|
+
await this._serviceContext.initialized.wait();
|
|
257
|
+
return this._serviceContext.dataSpaceManager!;
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
const identityService = new IdentityServiceImpl(
|
|
261
|
+
this._serviceContext.identityManager,
|
|
262
|
+
this._serviceContext.keyring,
|
|
263
|
+
() => this._serviceContext.dataSpaceManager!,
|
|
264
|
+
(params) => this._createIdentity(params),
|
|
265
|
+
(profile) => this._serviceContext.broadcastProfileUpdate(profile),
|
|
266
|
+
);
|
|
267
|
+
|
|
257
268
|
this._serviceRegistry.setServices({
|
|
258
269
|
SystemService: this._systemService,
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
(params) => this._createIdentity(params),
|
|
270
|
+
IdentityService: identityService,
|
|
271
|
+
ContactsService: new ContactsServiceImpl(
|
|
262
272
|
this._serviceContext.identityManager,
|
|
263
|
-
this._serviceContext.
|
|
264
|
-
|
|
273
|
+
this._serviceContext.spaceManager,
|
|
274
|
+
dataSpaceManagerProvider,
|
|
265
275
|
),
|
|
266
276
|
|
|
267
277
|
InvitationsService: new InvitationsServiceImpl(this._serviceContext.invitationsManager),
|
|
@@ -271,10 +281,7 @@ export class ClientServicesHost {
|
|
|
271
281
|
SpacesService: new SpacesServiceImpl(
|
|
272
282
|
this._serviceContext.identityManager,
|
|
273
283
|
this._serviceContext.spaceManager,
|
|
274
|
-
|
|
275
|
-
await this._serviceContext.initialized.wait();
|
|
276
|
-
return this._serviceContext.dataSpaceManager!;
|
|
277
|
-
},
|
|
284
|
+
dataSpaceManagerProvider,
|
|
278
285
|
),
|
|
279
286
|
|
|
280
287
|
DataService: this._serviceContext.echoHost.dataService,
|
|
@@ -294,6 +301,7 @@ export class ClientServicesHost {
|
|
|
294
301
|
});
|
|
295
302
|
|
|
296
303
|
await this._serviceContext.open(ctx);
|
|
304
|
+
await identityService.open();
|
|
297
305
|
|
|
298
306
|
const devtoolsProxy = this._config?.get('runtime.client.devtoolsProxy');
|
|
299
307
|
if (devtoolsProxy) {
|
|
@@ -349,34 +357,7 @@ export class ClientServicesHost {
|
|
|
349
357
|
|
|
350
358
|
private async _createIdentity(params: CreateIdentityOptions) {
|
|
351
359
|
const identity = await this._serviceContext.createIdentity(params);
|
|
352
|
-
|
|
353
|
-
// Setup default space.
|
|
354
360
|
await this._serviceContext.initialized.wait();
|
|
355
|
-
const space = await this._serviceContext.dataSpaceManager!.createSpace();
|
|
356
|
-
|
|
357
|
-
const automergeIndex = space.automergeSpaceState.rootUrl;
|
|
358
|
-
invariant(automergeIndex);
|
|
359
|
-
const document = this._serviceContext.echoHost.automergeRepo.find<SpaceDoc>(automergeIndex as any);
|
|
360
|
-
await document.whenReady();
|
|
361
|
-
|
|
362
|
-
// TODO(dmaretskyi): Better API for low-level data access.
|
|
363
|
-
const properties: ObjectStructure = {
|
|
364
|
-
system: {
|
|
365
|
-
type: encodeReference(getTypeReference(PropertiesType)!),
|
|
366
|
-
},
|
|
367
|
-
data: {
|
|
368
|
-
[defaultKey]: identity.identityKey.toHex(),
|
|
369
|
-
},
|
|
370
|
-
meta: {
|
|
371
|
-
keys: [],
|
|
372
|
-
},
|
|
373
|
-
};
|
|
374
|
-
const propertiesId = PublicKey.random().toHex();
|
|
375
|
-
document.change((doc: SpaceDoc) => {
|
|
376
|
-
assignDeep(doc, ['objects', propertiesId], properties);
|
|
377
|
-
});
|
|
378
|
-
|
|
379
|
-
await this._serviceContext.echoHost.flush();
|
|
380
361
|
return identity;
|
|
381
362
|
}
|
|
382
363
|
}
|
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { Event } from '@dxos/async';
|
|
6
|
+
import { Resource, type Context } from '@dxos/context';
|
|
6
7
|
import { type CredentialProcessor, type SpecificCredential, checkCredentialType } from '@dxos/credentials';
|
|
7
8
|
import { type Credential, type Epoch } from '@dxos/protocols/proto/dxos/halo/credentials';
|
|
8
9
|
|
|
9
|
-
export class AutomergeSpaceState implements CredentialProcessor {
|
|
10
|
+
export class AutomergeSpaceState extends Resource implements CredentialProcessor {
|
|
10
11
|
public rootUrl: string | undefined = undefined;
|
|
11
12
|
public lastEpoch: SpecificCredential<Epoch> | undefined = undefined;
|
|
12
13
|
|
|
@@ -14,7 +15,15 @@ export class AutomergeSpaceState implements CredentialProcessor {
|
|
|
14
15
|
|
|
15
16
|
private _isProcessingRootDocs = false;
|
|
16
17
|
|
|
17
|
-
constructor(private readonly _onNewRoot: (rootUrl: string) => void) {
|
|
18
|
+
constructor(private readonly _onNewRoot: (rootUrl: string) => void) {
|
|
19
|
+
super();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
protected override async _open(ctx: Context): Promise<void> {}
|
|
23
|
+
|
|
24
|
+
protected override async _close(ctx: Context): Promise<void> {
|
|
25
|
+
this._isProcessingRootDocs = false;
|
|
26
|
+
}
|
|
18
27
|
|
|
19
28
|
async processCredential(credential: Credential) {
|
|
20
29
|
if (!checkCredentialType(credential, 'dxos.halo.credentials.Epoch')) {
|
|
@@ -12,7 +12,7 @@ import { log } from '@dxos/log';
|
|
|
12
12
|
import { SpaceState } from '@dxos/protocols/proto/dxos/client/services';
|
|
13
13
|
import { describe, openAndClose, test } from '@dxos/test';
|
|
14
14
|
|
|
15
|
-
import { TestBuilder } from '../testing';
|
|
15
|
+
import { TestBuilder, type TestPeer } from '../testing';
|
|
16
16
|
|
|
17
17
|
describe('DataSpaceManager', () => {
|
|
18
18
|
test('create space', async () => {
|
|
@@ -168,5 +168,50 @@ describe('DataSpaceManager', () => {
|
|
|
168
168
|
500,
|
|
169
169
|
);
|
|
170
170
|
});
|
|
171
|
+
|
|
172
|
+
test('activate opens a lazily loaded space', async () => {
|
|
173
|
+
const builder = new TestBuilder();
|
|
174
|
+
|
|
175
|
+
const peer = builder.createPeer();
|
|
176
|
+
await peer.createIdentity();
|
|
177
|
+
await openAndClose(peer.echoHost, peer.dataSpaceManager);
|
|
178
|
+
|
|
179
|
+
await peer.dataSpaceManager.createSpace();
|
|
180
|
+
await reloadDataSpaces(peer);
|
|
181
|
+
|
|
182
|
+
const space = getFirstSpace(peer);
|
|
183
|
+
expect(space.state).to.equal(SpaceState.CLOSED);
|
|
184
|
+
await space.activate();
|
|
185
|
+
await asyncTimeout(
|
|
186
|
+
space.stateUpdate.waitForCondition(() => space.state === SpaceState.READY),
|
|
187
|
+
500,
|
|
188
|
+
);
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
test('deactivate lazily loaded space ', async () => {
|
|
192
|
+
const builder = new TestBuilder();
|
|
193
|
+
|
|
194
|
+
const peer = builder.createPeer();
|
|
195
|
+
await peer.createIdentity();
|
|
196
|
+
await openAndClose(peer.echoHost, peer.dataSpaceManager);
|
|
197
|
+
|
|
198
|
+
await peer.dataSpaceManager.createSpace();
|
|
199
|
+
await reloadDataSpaces(peer);
|
|
200
|
+
|
|
201
|
+
await getFirstSpace(peer).deactivate();
|
|
202
|
+
|
|
203
|
+
await reloadDataSpaces(peer);
|
|
204
|
+
|
|
205
|
+
expect(getFirstSpace(peer).state).to.eq(SpaceState.INACTIVE);
|
|
206
|
+
});
|
|
171
207
|
});
|
|
208
|
+
|
|
209
|
+
const reloadDataSpaces = async (peer: TestPeer) => {
|
|
210
|
+
await peer.dataSpaceManager.close();
|
|
211
|
+
await peer.dataSpaceManager.open();
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
const getFirstSpace = (peer: TestPeer) => {
|
|
215
|
+
return Array.from(peer.dataSpaceManager.spaces.values())[0];
|
|
216
|
+
};
|
|
172
217
|
});
|