@dxos/client-services 0.5.9-main.2dbe289 → 0.5.9-main.405fda7
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-QWL2M4EU.mjs → chunk-NBUF5LMA.mjs} +743 -605
- package/dist/lib/browser/chunk-NBUF5LMA.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +1 -1
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/packlets/testing/index.mjs +11 -11
- package/dist/lib/browser/packlets/testing/index.mjs.map +3 -3
- package/dist/lib/node/{chunk-NPYJIVOX.cjs → chunk-CMHCDXY6.cjs} +959 -825
- package/dist/lib/node/chunk-CMHCDXY6.cjs.map +7 -0
- package/dist/lib/node/index.cjs +42 -42
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/packlets/testing/index.cjs +17 -17
- package/dist/lib/node/packlets/testing/index.cjs.map +3 -3
- 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/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/data-space-manager.d.ts +5 -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.map +1 -1
- 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/default-space-state-machine.ts +44 -0
- package/src/packlets/identity/identity-service.test.ts +35 -5
- package/src/packlets/identity/identity-service.ts +50 -8
- package/src/packlets/identity/identity.ts +25 -2
- package/src/packlets/services/service-context.ts +1 -4
- package/src/packlets/services/service-host.ts +13 -40
- package/src/packlets/spaces/data-space-manager.test.ts +46 -1
- package/src/packlets/spaces/data-space-manager.ts +54 -25
- package/src/packlets/spaces/data-space.ts +9 -5
- package/src/packlets/testing/test-builder.ts +12 -10
- package/src/version.ts +1 -1
- package/dist/lib/browser/chunk-QWL2M4EU.mjs.map +0 -7
- package/dist/lib/node/chunk-NPYJIVOX.cjs.map +0 -7
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
import { Event, synchronized, trackLeaks } from '@dxos/async';
|
|
6
6
|
import { type Doc } from '@dxos/automerge/automerge';
|
|
7
|
-
import { type AutomergeUrl } from '@dxos/automerge/automerge-repo';
|
|
7
|
+
import { type DocHandle, type AutomergeUrl } from '@dxos/automerge/automerge-repo';
|
|
8
|
+
import { PropertiesType } from '@dxos/client-protocol';
|
|
8
9
|
import { cancelWithContext, Context } from '@dxos/context';
|
|
9
10
|
import {
|
|
10
11
|
type CredentialSigner,
|
|
@@ -21,7 +22,8 @@ import {
|
|
|
21
22
|
type SpaceProtocol,
|
|
22
23
|
type SpaceProtocolSession,
|
|
23
24
|
} from '@dxos/echo-pipeline';
|
|
24
|
-
import { type SpaceDoc } from '@dxos/echo-protocol';
|
|
25
|
+
import { encodeReference, type ObjectStructure, type SpaceDoc } from '@dxos/echo-protocol';
|
|
26
|
+
import { generateEchoId, getTypeReference } from '@dxos/echo-schema';
|
|
25
27
|
import { type FeedStore } from '@dxos/feed-store';
|
|
26
28
|
import { invariant } from '@dxos/invariant';
|
|
27
29
|
import { type Keyring } from '@dxos/keyring';
|
|
@@ -37,7 +39,7 @@ import { type PeerState } from '@dxos/protocols/proto/dxos/mesh/presence';
|
|
|
37
39
|
import { Gossip, Presence } from '@dxos/teleport-extension-gossip';
|
|
38
40
|
import { type Timeframe } from '@dxos/timeframe';
|
|
39
41
|
import { trace } from '@dxos/tracing';
|
|
40
|
-
import { ComplexMap, deferFunction, forEachAsync } from '@dxos/util';
|
|
42
|
+
import { assignDeep, ComplexMap, deferFunction, forEachAsync } from '@dxos/util';
|
|
41
43
|
|
|
42
44
|
import { DataSpace, findPropertiesObject } from './data-space';
|
|
43
45
|
import { spaceGenesis } from './genesis';
|
|
@@ -47,6 +49,9 @@ import { type InvitationsManager } from '../invitations';
|
|
|
47
49
|
const PRESENCE_ANNOUNCE_INTERVAL = 10_000;
|
|
48
50
|
const PRESENCE_OFFLINE_TIMEOUT = 20_000;
|
|
49
51
|
|
|
52
|
+
// Space properties key for default metadata.
|
|
53
|
+
const DEFAULT_SPACE_KEY = '__DEFAULT__';
|
|
54
|
+
|
|
50
55
|
export interface SigningContext {
|
|
51
56
|
identityKey: PublicKey;
|
|
52
57
|
deviceKey: PublicKey;
|
|
@@ -88,8 +93,6 @@ export class DataSpaceManager {
|
|
|
88
93
|
|
|
89
94
|
private _isOpen = false;
|
|
90
95
|
private readonly _instanceId = PublicKey.random().toHex();
|
|
91
|
-
private readonly _spaceMemberPresenceAnnounceInterval: number;
|
|
92
|
-
private readonly _spaceMemberPresenceOfflineTimeout: number;
|
|
93
96
|
|
|
94
97
|
constructor(
|
|
95
98
|
private readonly _spaceManager: SpaceManager,
|
|
@@ -99,15 +102,8 @@ export class DataSpaceManager {
|
|
|
99
102
|
private readonly _feedStore: FeedStore<FeedMessage>,
|
|
100
103
|
private readonly _echoHost: EchoHost,
|
|
101
104
|
private readonly _invitationsManager: InvitationsManager,
|
|
102
|
-
|
|
105
|
+
private readonly _params?: DataSpaceManagerRuntimeParams,
|
|
103
106
|
) {
|
|
104
|
-
const {
|
|
105
|
-
spaceMemberPresenceAnnounceInterval = PRESENCE_ANNOUNCE_INTERVAL,
|
|
106
|
-
spaceMemberPresenceOfflineTimeout = PRESENCE_OFFLINE_TIMEOUT,
|
|
107
|
-
} = params ?? {};
|
|
108
|
-
this._spaceMemberPresenceAnnounceInterval = spaceMemberPresenceAnnounceInterval;
|
|
109
|
-
this._spaceMemberPresenceOfflineTimeout = spaceMemberPresenceOfflineTimeout;
|
|
110
|
-
|
|
111
107
|
trace.diagnostic({
|
|
112
108
|
id: 'spaces',
|
|
113
109
|
name: 'Spaces',
|
|
@@ -157,12 +153,6 @@ export class DataSpaceManager {
|
|
|
157
153
|
this._isOpen = true;
|
|
158
154
|
this.updated.emit();
|
|
159
155
|
|
|
160
|
-
for (const space of this._spaces.values()) {
|
|
161
|
-
if (space.state !== SpaceState.INACTIVE) {
|
|
162
|
-
space.initializeDataPipelineAsync();
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
156
|
log.trace('dxos.echo.data-space-manager.open', Trace.end({ id: this._instanceId }));
|
|
167
157
|
}
|
|
168
158
|
|
|
@@ -174,6 +164,7 @@ export class DataSpaceManager {
|
|
|
174
164
|
for (const space of this._spaces.values()) {
|
|
175
165
|
await space.close();
|
|
176
166
|
}
|
|
167
|
+
this._spaces.clear();
|
|
177
168
|
}
|
|
178
169
|
|
|
179
170
|
/**
|
|
@@ -197,6 +188,7 @@ export class DataSpaceManager {
|
|
|
197
188
|
|
|
198
189
|
const root = await this._echoHost.createSpaceRoot(spaceKey);
|
|
199
190
|
const space = await this._constructSpace(metadata);
|
|
191
|
+
await space.open();
|
|
200
192
|
|
|
201
193
|
const credentials = await spaceGenesis(this._keyring, this._signingContext, space.inner, root.url);
|
|
202
194
|
await this._metadataStore.addSpace(metadata);
|
|
@@ -211,6 +203,46 @@ export class DataSpaceManager {
|
|
|
211
203
|
return space;
|
|
212
204
|
}
|
|
213
205
|
|
|
206
|
+
async isDefaultSpace(space: DataSpace): Promise<boolean> {
|
|
207
|
+
const rootDoc = await this._getSpaceRootDocument(space);
|
|
208
|
+
const [_, properties] = findPropertiesObject(rootDoc.docSync()) ?? [];
|
|
209
|
+
return properties?.data?.[DEFAULT_SPACE_KEY] === this._signingContext.identityKey.toHex();
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
async createDefaultSpace() {
|
|
213
|
+
const space = await this.createSpace();
|
|
214
|
+
const document = await this._getSpaceRootDocument(space);
|
|
215
|
+
|
|
216
|
+
// TODO(dmaretskyi): Better API for low-level data access.
|
|
217
|
+
const properties: ObjectStructure = {
|
|
218
|
+
system: {
|
|
219
|
+
type: encodeReference(getTypeReference(PropertiesType)!),
|
|
220
|
+
},
|
|
221
|
+
data: {
|
|
222
|
+
[DEFAULT_SPACE_KEY]: this._signingContext.identityKey.toHex(),
|
|
223
|
+
},
|
|
224
|
+
meta: {
|
|
225
|
+
keys: [],
|
|
226
|
+
},
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
const propertiesId = generateEchoId();
|
|
230
|
+
document.change((doc: SpaceDoc) => {
|
|
231
|
+
assignDeep(doc, ['objects', propertiesId], properties);
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
await this._echoHost.flush();
|
|
235
|
+
return space;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
private async _getSpaceRootDocument(space: DataSpace): Promise<DocHandle<SpaceDoc>> {
|
|
239
|
+
const automergeIndex = space.automergeSpaceState.rootUrl;
|
|
240
|
+
invariant(automergeIndex);
|
|
241
|
+
const document = this._echoHost.automergeRepo.find<SpaceDoc>(automergeIndex as any);
|
|
242
|
+
await document.whenReady();
|
|
243
|
+
return document;
|
|
244
|
+
}
|
|
245
|
+
|
|
214
246
|
// TODO(burdon): Rename join space.
|
|
215
247
|
@synchronized
|
|
216
248
|
async acceptSpace(opts: AcceptSpaceOptions): Promise<DataSpace> {
|
|
@@ -226,6 +258,7 @@ export class DataSpaceManager {
|
|
|
226
258
|
};
|
|
227
259
|
|
|
228
260
|
const space = await this._constructSpace(metadata);
|
|
261
|
+
await space.open();
|
|
229
262
|
await this._metadataStore.addSpace(metadata);
|
|
230
263
|
space.initializeDataPipelineAsync();
|
|
231
264
|
|
|
@@ -254,8 +287,8 @@ export class DataSpaceManager {
|
|
|
254
287
|
localPeerId: this._signingContext.deviceKey,
|
|
255
288
|
});
|
|
256
289
|
const presence = new Presence({
|
|
257
|
-
announceInterval: this.
|
|
258
|
-
offlineTimeout: this.
|
|
290
|
+
announceInterval: this._params?.spaceMemberPresenceAnnounceInterval ?? PRESENCE_ANNOUNCE_INTERVAL,
|
|
291
|
+
offlineTimeout: this._params?.spaceMemberPresenceOfflineTimeout ?? PRESENCE_OFFLINE_TIMEOUT,
|
|
259
292
|
identityKey: this._signingContext.identityKey,
|
|
260
293
|
gossip,
|
|
261
294
|
});
|
|
@@ -336,10 +369,6 @@ export class DataSpaceManager {
|
|
|
336
369
|
}
|
|
337
370
|
});
|
|
338
371
|
|
|
339
|
-
if (metadata.state !== SpaceState.INACTIVE) {
|
|
340
|
-
await dataSpace.open();
|
|
341
|
-
}
|
|
342
|
-
|
|
343
372
|
if (metadata.controlTimeframe) {
|
|
344
373
|
dataSpace.inner.controlPipeline.state.setTargetTimeframe(metadata.controlTimeframe);
|
|
345
374
|
}
|
|
@@ -193,10 +193,13 @@ export class DataSpace {
|
|
|
193
193
|
|
|
194
194
|
@synchronized
|
|
195
195
|
async open() {
|
|
196
|
-
|
|
196
|
+
if (this._state === SpaceState.CLOSED) {
|
|
197
|
+
await this._open();
|
|
198
|
+
}
|
|
197
199
|
}
|
|
198
200
|
|
|
199
201
|
private async _open() {
|
|
202
|
+
await this._presence.open();
|
|
200
203
|
await this._gossip.open();
|
|
201
204
|
await this._notarizationPlugin.open();
|
|
202
205
|
await this._inner.spaceState.addCredentialProcessor(this._notarizationPlugin);
|
|
@@ -228,7 +231,7 @@ export class DataSpace {
|
|
|
228
231
|
await this._inner.spaceState.removeCredentialProcessor(this._notarizationPlugin);
|
|
229
232
|
await this._notarizationPlugin.close();
|
|
230
233
|
|
|
231
|
-
await this._presence.
|
|
234
|
+
await this._presence.close();
|
|
232
235
|
await this._gossip.close();
|
|
233
236
|
}
|
|
234
237
|
|
|
@@ -545,7 +548,7 @@ export class DataSpace {
|
|
|
545
548
|
|
|
546
549
|
@synchronized
|
|
547
550
|
async activate() {
|
|
548
|
-
if (
|
|
551
|
+
if (![SpaceState.CLOSED, SpaceState.INACTIVE].includes(this._state)) {
|
|
549
552
|
return;
|
|
550
553
|
}
|
|
551
554
|
|
|
@@ -559,10 +562,11 @@ export class DataSpace {
|
|
|
559
562
|
if (this._state === SpaceState.INACTIVE) {
|
|
560
563
|
return;
|
|
561
564
|
}
|
|
562
|
-
|
|
563
565
|
// Unregister from data service.
|
|
564
566
|
await this._metadataStore.setSpaceState(this.key, SpaceState.INACTIVE);
|
|
565
|
-
|
|
567
|
+
if (this._state !== SpaceState.CLOSED) {
|
|
568
|
+
await this._close();
|
|
569
|
+
}
|
|
566
570
|
this._state = SpaceState.INACTIVE;
|
|
567
571
|
log('new state', { state: SpaceState[this._state] });
|
|
568
572
|
this.stateUpdate.emit();
|
|
@@ -19,8 +19,8 @@ import { createStorage, StorageType, type Storage } from '@dxos/random-access-st
|
|
|
19
19
|
import { BlobStore } from '@dxos/teleport-extension-object-sync';
|
|
20
20
|
|
|
21
21
|
import { InvitationsHandler, InvitationsManager, SpaceInvitationProtocol } from '../invitations';
|
|
22
|
-
import { ClientServicesHost, ServiceContext } from '../services';
|
|
23
|
-
import { DataSpaceManager, type SigningContext } from '../spaces';
|
|
22
|
+
import { ClientServicesHost, ServiceContext, type ServiceContextRuntimeParams } from '../services';
|
|
23
|
+
import { DataSpaceManager, type DataSpaceManagerRuntimeParams, type SigningContext } from '../spaces';
|
|
24
24
|
|
|
25
25
|
//
|
|
26
26
|
// TODO(burdon): Replace with test builder.
|
|
@@ -37,9 +37,11 @@ export const createServiceHost = (config: Config, signalManagerContext: MemorySi
|
|
|
37
37
|
export const createServiceContext = async ({
|
|
38
38
|
signalContext = new MemorySignalManagerContext(),
|
|
39
39
|
storage = createStorage({ type: StorageType.RAM }),
|
|
40
|
+
runtimeParams,
|
|
40
41
|
}: {
|
|
41
42
|
signalContext?: MemorySignalManagerContext;
|
|
42
43
|
storage?: Storage;
|
|
44
|
+
runtimeParams?: ServiceContextRuntimeParams;
|
|
43
45
|
} = {}) => {
|
|
44
46
|
const signalManager = new MemorySignalManager(signalContext);
|
|
45
47
|
const networkManager = new SwarmNetworkManager({
|
|
@@ -51,6 +53,7 @@ export const createServiceContext = async ({
|
|
|
51
53
|
|
|
52
54
|
return new ServiceContext(storage, level, networkManager, signalManager, {
|
|
53
55
|
invitationConnectionDefaultParams: { controlHeartbeatInterval: 200 },
|
|
56
|
+
...runtimeParams,
|
|
54
57
|
});
|
|
55
58
|
};
|
|
56
59
|
|
|
@@ -88,6 +91,7 @@ export class TestBuilder {
|
|
|
88
91
|
|
|
89
92
|
export type TestPeerOpts = {
|
|
90
93
|
dataStore?: StorageType;
|
|
94
|
+
dataSpaceParams?: DataSpaceManagerRuntimeParams;
|
|
91
95
|
};
|
|
92
96
|
|
|
93
97
|
export type TestPeerProps = {
|
|
@@ -110,8 +114,8 @@ export class TestPeer {
|
|
|
110
114
|
private _props: TestPeerProps = {};
|
|
111
115
|
|
|
112
116
|
constructor(
|
|
113
|
-
private readonly
|
|
114
|
-
private readonly
|
|
117
|
+
private readonly _signalContext: MemorySignalManagerContext,
|
|
118
|
+
private readonly _opts: TestPeerOpts = { dataStore: StorageType.RAM },
|
|
115
119
|
) {}
|
|
116
120
|
|
|
117
121
|
get props() {
|
|
@@ -119,7 +123,7 @@ export class TestPeer {
|
|
|
119
123
|
}
|
|
120
124
|
|
|
121
125
|
get storage() {
|
|
122
|
-
return (this._props.storage ??= createStorage({ type: this.
|
|
126
|
+
return (this._props.storage ??= createStorage({ type: this._opts.dataStore }));
|
|
123
127
|
}
|
|
124
128
|
|
|
125
129
|
get keyring() {
|
|
@@ -156,7 +160,7 @@ export class TestPeer {
|
|
|
156
160
|
|
|
157
161
|
get networkManager() {
|
|
158
162
|
return (this._props.networkManager ??= new SwarmNetworkManager({
|
|
159
|
-
signalManager: new MemorySignalManager(this.
|
|
163
|
+
signalManager: new MemorySignalManager(this._signalContext),
|
|
160
164
|
transportFactory: MemoryTransportFactory,
|
|
161
165
|
}));
|
|
162
166
|
}
|
|
@@ -176,10 +180,7 @@ export class TestPeer {
|
|
|
176
180
|
}
|
|
177
181
|
|
|
178
182
|
get echoHost() {
|
|
179
|
-
return (this._props.echoHost ??= new EchoHost({
|
|
180
|
-
kv: this.level,
|
|
181
|
-
storage: this.storage,
|
|
182
|
-
}));
|
|
183
|
+
return (this._props.echoHost ??= new EchoHost({ kv: this.level }));
|
|
183
184
|
}
|
|
184
185
|
|
|
185
186
|
get dataSpaceManager(): DataSpaceManager {
|
|
@@ -191,6 +192,7 @@ export class TestPeer {
|
|
|
191
192
|
this.feedStore,
|
|
192
193
|
this.echoHost,
|
|
193
194
|
this.invitationsManager,
|
|
195
|
+
this._opts.dataSpaceParams,
|
|
194
196
|
));
|
|
195
197
|
}
|
|
196
198
|
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const DXOS_VERSION = "0.5.9-main.
|
|
1
|
+
export const DXOS_VERSION = "0.5.9-main.405fda7";
|