@dxos/client-services 0.1.58-main.ffbb8a1 → 0.1.58-next.6d0af18
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-YLR3BYMV.mjs → chunk-DJ4JCFP7.mjs} +271 -191
- package/dist/lib/browser/chunk-DJ4JCFP7.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +11 -11
- 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 +5 -5
- package/dist/lib/browser/packlets/testing/index.mjs.map +3 -3
- package/dist/lib/node/index.cjs +313 -233
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/packlets/testing/index.cjs +310 -230
- package/dist/lib/node/packlets/testing/index.cjs.map +4 -4
- package/dist/types/src/packlets/devtools/devtools.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/authenticator.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts +1 -1
- package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitation-extension.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitations-handler.d.ts +3 -3
- package/dist/types/src/packlets/invitations/invitations-handler.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 +1 -1
- package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts.map +1 -1
- package/dist/types/src/packlets/services/diagnostics.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 -0
- package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/data-space.d.ts +1 -1
- package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/spaces-service.d.ts +2 -2
- package/dist/types/src/packlets/spaces/spaces-service.d.ts.map +1 -1
- package/dist/types/src/packlets/testing/invitation-utils.d.ts +5 -5
- package/dist/types/src/packlets/testing/invitation-utils.d.ts.map +1 -1
- package/dist/types/src/packlets/testing/test-builder.d.ts +1 -1
- package/dist/types/src/packlets/testing/test-builder.d.ts.map +1 -1
- package/dist/types/src/packlets/vault/iframe-host-runtime.d.ts.map +1 -1
- package/dist/types/src/packlets/vault/shell-runtime.d.ts +1 -1
- package/dist/types/src/packlets/vault/shell-runtime.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 +35 -35
- package/src/packlets/devices/devices-service.test.ts +1 -1
- package/src/packlets/devtools/devtools.ts +1 -1
- package/src/packlets/identity/authenticator.ts +2 -5
- package/src/packlets/identity/identity-manager.test.ts +1 -1
- package/src/packlets/identity/identity-service.test.ts +1 -1
- package/src/packlets/identity/identity.test.ts +1 -1
- package/src/packlets/invitations/device-invitation-protocol.ts +1 -1
- package/src/packlets/invitations/invitation-extension.ts +1 -2
- package/src/packlets/invitations/invitations-handler.ts +7 -8
- package/src/packlets/invitations/invitations-service.ts +11 -5
- package/src/packlets/invitations/space-invitation-protocol.ts +1 -1
- package/src/packlets/network/network-service.test.ts +1 -1
- package/src/packlets/services/diagnostics.ts +2 -2
- package/src/packlets/services/service-context.ts +7 -13
- package/src/packlets/services/service-host.test.ts +3 -3
- package/src/packlets/services/service-host.ts +42 -6
- package/src/packlets/services/service-registry.test.ts +1 -1
- package/src/packlets/spaces/data-space-manager.test.ts +1 -1
- package/src/packlets/spaces/data-space-manager.ts +1 -1
- package/src/packlets/spaces/data-space.ts +11 -3
- package/src/packlets/spaces/spaces-service.test.ts +1 -1
- package/src/packlets/spaces/spaces-service.ts +31 -10
- package/src/packlets/storage/storage.ts +10 -10
- package/src/packlets/testing/invitation-utils.ts +9 -9
- package/src/packlets/testing/test-builder.ts +3 -3
- package/src/packlets/vault/iframe-host-runtime.ts +1 -1
- package/src/packlets/vault/iframe-proxy-runtime.ts +1 -1
- package/src/packlets/vault/shell-runtime.ts +4 -4
- package/src/packlets/vault/worker-runtime.ts +9 -6
- package/src/version.ts +1 -1
- package/dist/lib/browser/chunk-YLR3BYMV.mjs.map +0 -7
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { Event } from '@dxos/async';
|
|
6
|
-
import {
|
|
6
|
+
import { AuthenticatingInvitation, CancellableInvitation } from '@dxos/client-protocol';
|
|
7
7
|
import { Stream } from '@dxos/codec-protobuf';
|
|
8
8
|
import { invariant } from '@dxos/invariant';
|
|
9
9
|
import { log } from '@dxos/log';
|
|
@@ -21,8 +21,8 @@ import { InvitationsHandler } from './invitations-handler';
|
|
|
21
21
|
* Adapts invitation service observable to client/service stream.
|
|
22
22
|
*/
|
|
23
23
|
export class InvitationsServiceImpl implements InvitationsService {
|
|
24
|
-
private readonly _createInvitations = new Map<string,
|
|
25
|
-
private readonly _acceptInvitations = new Map<string,
|
|
24
|
+
private readonly _createInvitations = new Map<string, CancellableInvitation>();
|
|
25
|
+
private readonly _acceptInvitations = new Map<string, AuthenticatingInvitation>();
|
|
26
26
|
private readonly _invitationCreated = new Event<Invitation>();
|
|
27
27
|
private readonly _invitationAccepted = new Event<Invitation>();
|
|
28
28
|
private readonly _removedCreated = new Event<Invitation>();
|
|
@@ -41,7 +41,7 @@ export class InvitationsServiceImpl implements InvitationsService {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
createInvitation(options: Invitation): Stream<Invitation> {
|
|
44
|
-
let invitation:
|
|
44
|
+
let invitation: CancellableInvitation;
|
|
45
45
|
|
|
46
46
|
const existingInvitation = this._createInvitations.get(options.invitationId);
|
|
47
47
|
if (existingInvitation) {
|
|
@@ -64,13 +64,16 @@ export class InvitationsServiceImpl implements InvitationsService {
|
|
|
64
64
|
() => {
|
|
65
65
|
close();
|
|
66
66
|
this._createInvitations.delete(invitation.get().invitationId);
|
|
67
|
+
if (invitation.get().type !== Invitation.Type.MULTIUSE) {
|
|
68
|
+
this._removedCreated.emit(invitation.get());
|
|
69
|
+
}
|
|
67
70
|
},
|
|
68
71
|
);
|
|
69
72
|
});
|
|
70
73
|
}
|
|
71
74
|
|
|
72
75
|
acceptInvitation(options: Invitation): Stream<Invitation> {
|
|
73
|
-
let invitation:
|
|
76
|
+
let invitation: AuthenticatingInvitation;
|
|
74
77
|
|
|
75
78
|
const existingInvitation = this._acceptInvitations.get(options.invitationId);
|
|
76
79
|
if (existingInvitation) {
|
|
@@ -93,6 +96,9 @@ export class InvitationsServiceImpl implements InvitationsService {
|
|
|
93
96
|
() => {
|
|
94
97
|
close();
|
|
95
98
|
this._acceptInvitations.delete(invitation.get().invitationId);
|
|
99
|
+
if (invitation.get().type !== Invitation.Type.MULTIUSE) {
|
|
100
|
+
this._removedAccepted.emit(invitation.get());
|
|
101
|
+
}
|
|
96
102
|
},
|
|
97
103
|
);
|
|
98
104
|
});
|
|
@@ -13,8 +13,8 @@ import { FeedMessage } from '@dxos/protocols/proto/dxos/echo/feed';
|
|
|
13
13
|
import { ProfileDocument } from '@dxos/protocols/proto/dxos/halo/credentials';
|
|
14
14
|
import { AdmissionRequest, AdmissionResponse, IntroductionRequest } from '@dxos/protocols/proto/dxos/halo/invitations';
|
|
15
15
|
|
|
16
|
-
import { DataSpaceManager, SigningContext } from '../spaces';
|
|
17
16
|
import { InvitationProtocol } from './invitation-protocol';
|
|
17
|
+
import { DataSpaceManager, SigningContext } from '../spaces';
|
|
18
18
|
|
|
19
19
|
export class SpaceInvitationProtocol implements InvitationProtocol {
|
|
20
20
|
constructor(
|
|
@@ -9,9 +9,9 @@ import { Context } from '@dxos/context';
|
|
|
9
9
|
import { NetworkService, ConnectionState } from '@dxos/protocols/proto/dxos/client/services';
|
|
10
10
|
import { afterEach, afterTest, beforeEach, describe, test } from '@dxos/test';
|
|
11
11
|
|
|
12
|
+
import { NetworkServiceImpl } from './network-service';
|
|
12
13
|
import { ServiceContext } from '../services';
|
|
13
14
|
import { createServiceContext } from '../testing';
|
|
14
|
-
import { NetworkServiceImpl } from './network-service';
|
|
15
15
|
|
|
16
16
|
describe('NetworkService', () => {
|
|
17
17
|
let serviceContext: ServiceContext;
|
|
@@ -22,10 +22,10 @@ import {
|
|
|
22
22
|
import { SubscribeToFeedsResponse } from '@dxos/protocols/proto/dxos/devtools/host';
|
|
23
23
|
import { Epoch } from '@dxos/protocols/proto/dxos/halo/credentials';
|
|
24
24
|
|
|
25
|
-
import { DXOS_VERSION } from '../../version';
|
|
26
|
-
import { DataSpace } from '../spaces';
|
|
27
25
|
import { getPlatform, Platform } from './platform';
|
|
28
26
|
import { ServiceContext } from './service-context';
|
|
27
|
+
import { DXOS_VERSION } from '../../version';
|
|
28
|
+
import { DataSpace } from '../spaces';
|
|
29
29
|
|
|
30
30
|
const DEFAULT_TIMEOUT = 1_000;
|
|
31
31
|
|
|
@@ -21,7 +21,7 @@ import { log } from '@dxos/log';
|
|
|
21
21
|
import { SignalManager } from '@dxos/messaging';
|
|
22
22
|
import { ModelFactory } from '@dxos/model-factory';
|
|
23
23
|
import { NetworkManager } from '@dxos/network-manager';
|
|
24
|
-
import { STORAGE_VERSION, trace } from '@dxos/protocols';
|
|
24
|
+
import { InvalidStorageVersionError, STORAGE_VERSION, trace } from '@dxos/protocols';
|
|
25
25
|
import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
|
|
26
26
|
import type { FeedMessage } from '@dxos/protocols/proto/dxos/echo/feed';
|
|
27
27
|
import { Credential } from '@dxos/protocols/proto/dxos/halo/credentials';
|
|
@@ -73,12 +73,11 @@ export class ServiceContext {
|
|
|
73
73
|
|
|
74
74
|
private readonly _instanceId = PublicKey.random().toHex();
|
|
75
75
|
|
|
76
|
-
// prettier-ignore
|
|
77
76
|
constructor(
|
|
78
77
|
public readonly storage: Storage,
|
|
79
78
|
public readonly networkManager: NetworkManager,
|
|
80
79
|
public readonly signalManager: SignalManager,
|
|
81
|
-
public readonly modelFactory: ModelFactory
|
|
80
|
+
public readonly modelFactory: ModelFactory,
|
|
82
81
|
) {
|
|
83
82
|
// TODO(burdon): Move strings to constants.
|
|
84
83
|
this.metadataStore = new MetadataStore(storage.createDirectory('metadata'));
|
|
@@ -94,7 +93,7 @@ export class ServiceContext {
|
|
|
94
93
|
valueEncoding,
|
|
95
94
|
stats: true,
|
|
96
95
|
},
|
|
97
|
-
})
|
|
96
|
+
}),
|
|
98
97
|
});
|
|
99
98
|
|
|
100
99
|
this.spaceManager = new SpaceManager({
|
|
@@ -106,12 +105,7 @@ export class ServiceContext {
|
|
|
106
105
|
snapshotStore: this.snapshotStore,
|
|
107
106
|
});
|
|
108
107
|
|
|
109
|
-
this.identityManager = new IdentityManager(
|
|
110
|
-
this.metadataStore,
|
|
111
|
-
this.keyring,
|
|
112
|
-
this.feedStore,
|
|
113
|
-
this.spaceManager
|
|
114
|
-
);
|
|
108
|
+
this.identityManager = new IdentityManager(this.metadataStore, this.keyring, this.feedStore, this.spaceManager);
|
|
115
109
|
|
|
116
110
|
this.invitations = new InvitationsHandler(this.networkManager);
|
|
117
111
|
|
|
@@ -123,8 +117,8 @@ export class ServiceContext {
|
|
|
123
117
|
new DeviceInvitationProtocol(
|
|
124
118
|
this.keyring,
|
|
125
119
|
() => this.identityManager.identity ?? failUndefined(),
|
|
126
|
-
this._acceptIdentity.bind(this)
|
|
127
|
-
)
|
|
120
|
+
this._acceptIdentity.bind(this),
|
|
121
|
+
),
|
|
128
122
|
);
|
|
129
123
|
}
|
|
130
124
|
|
|
@@ -184,7 +178,7 @@ export class ServiceContext {
|
|
|
184
178
|
private async _checkStorageVersion() {
|
|
185
179
|
await this.metadataStore.load();
|
|
186
180
|
if (this.metadataStore.version !== STORAGE_VERSION) {
|
|
187
|
-
throw new
|
|
181
|
+
throw new InvalidStorageVersionError(STORAGE_VERSION, this.metadataStore.version);
|
|
188
182
|
// TODO(mykola): Migrate storage to a new version if incompatibility is detected.
|
|
189
183
|
}
|
|
190
184
|
}
|
|
@@ -22,11 +22,11 @@ import { createMockCredential, createServiceHost } from '../testing';
|
|
|
22
22
|
chai.use(chaiAsPromised);
|
|
23
23
|
|
|
24
24
|
describe('ClientServicesHost', () => {
|
|
25
|
-
const
|
|
25
|
+
const dataRoot = '/tmp/dxos/client-services/service-host/storage';
|
|
26
26
|
|
|
27
27
|
afterEach(async () => {
|
|
28
28
|
// Clean up.
|
|
29
|
-
isNode() && rmSync(
|
|
29
|
+
isNode() && rmSync(dataRoot, { recursive: true, force: true });
|
|
30
30
|
});
|
|
31
31
|
|
|
32
32
|
test('queryCredentials', async () => {
|
|
@@ -114,7 +114,7 @@ describe('ClientServicesHost', () => {
|
|
|
114
114
|
|
|
115
115
|
test('storage reset', async () => {
|
|
116
116
|
const config = new Config({
|
|
117
|
-
runtime: { client: { storage: { persistent: true,
|
|
117
|
+
runtime: { client: { storage: { persistent: true, dataRoot } } },
|
|
118
118
|
});
|
|
119
119
|
{
|
|
120
120
|
const host = createServiceHost(config, new MemorySignalManagerContext());
|
|
@@ -3,11 +3,12 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { Event, synchronized } from '@dxos/async';
|
|
6
|
-
import { clientServiceBundle, ClientServices } from '@dxos/client-protocol';
|
|
6
|
+
import { clientServiceBundle, ClientServices, defaultKey, Properties } from '@dxos/client-protocol';
|
|
7
7
|
import { Config } from '@dxos/config';
|
|
8
8
|
import { Context } from '@dxos/context';
|
|
9
9
|
import { DocumentModel } from '@dxos/document-model';
|
|
10
10
|
import { DataServiceImpl } from '@dxos/echo-pipeline';
|
|
11
|
+
import { TypedObject, base } from '@dxos/echo-schema';
|
|
11
12
|
import { invariant } from '@dxos/invariant';
|
|
12
13
|
import { PublicKey } from '@dxos/keys';
|
|
13
14
|
import { log } from '@dxos/log';
|
|
@@ -16,14 +17,18 @@ import { ModelFactory } from '@dxos/model-factory';
|
|
|
16
17
|
import { createSimplePeerTransportFactory, NetworkManager, TransportFactory } from '@dxos/network-manager';
|
|
17
18
|
import { trace } from '@dxos/protocols';
|
|
18
19
|
import { SystemStatus } from '@dxos/protocols/proto/dxos/client/services';
|
|
20
|
+
import { EchoObject } from '@dxos/protocols/proto/dxos/echo/object';
|
|
19
21
|
import { Storage } from '@dxos/random-access-storage';
|
|
20
22
|
import { TextModel } from '@dxos/text-model';
|
|
21
23
|
import { TRACE_PROCESSOR, trace as Trace } from '@dxos/tracing';
|
|
22
24
|
import { WebsocketRpcClient } from '@dxos/websocket-rpc';
|
|
23
25
|
|
|
26
|
+
import { createDiagnostics } from './diagnostics';
|
|
27
|
+
import { ServiceContext } from './service-context';
|
|
28
|
+
import { ServiceRegistry } from './service-registry';
|
|
24
29
|
import { DevicesServiceImpl } from '../devices';
|
|
25
30
|
import { DevtoolsServiceImpl, DevtoolsHostEvents } from '../devtools';
|
|
26
|
-
import { IdentityServiceImpl } from '../identity';
|
|
31
|
+
import { CreateIdentityOptions, IdentityServiceImpl } from '../identity';
|
|
27
32
|
import { InvitationsServiceImpl } from '../invitations';
|
|
28
33
|
import { Lock, ResourceLock } from '../locks';
|
|
29
34
|
import { LoggingServiceImpl } from '../logging';
|
|
@@ -31,15 +36,27 @@ import { NetworkServiceImpl } from '../network';
|
|
|
31
36
|
import { SpacesServiceImpl } from '../spaces';
|
|
32
37
|
import { createStorageObjects } from '../storage';
|
|
33
38
|
import { SystemServiceImpl } from '../system';
|
|
34
|
-
import { createDiagnostics } from './diagnostics';
|
|
35
|
-
import { ServiceContext } from './service-context';
|
|
36
|
-
import { ServiceRegistry } from './service-registry';
|
|
37
39
|
|
|
38
40
|
// TODO(burdon): Factor out to spaces.
|
|
39
41
|
export const createDefaultModelFactory = () => {
|
|
40
42
|
return new ModelFactory().registerModel(DocumentModel).registerModel(TextModel);
|
|
41
43
|
};
|
|
42
44
|
|
|
45
|
+
// TODO(wittjosiah): Factor out.
|
|
46
|
+
const createGenesisMutationFromTypedObject = (obj: TypedObject): EchoObject => {
|
|
47
|
+
const snapshot = obj[base]._createSnapshot();
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
objectId: obj[base]._id,
|
|
51
|
+
genesis: {
|
|
52
|
+
modelType: obj[base]._modelConstructor.meta.type,
|
|
53
|
+
},
|
|
54
|
+
snapshot: {
|
|
55
|
+
model: snapshot,
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
|
|
43
60
|
export type ClientServicesHostParams = {
|
|
44
61
|
/**
|
|
45
62
|
* Can be omitted if `initialize` is later called.
|
|
@@ -243,7 +260,7 @@ export class ClientServicesHost {
|
|
|
243
260
|
SystemService: this._systemService,
|
|
244
261
|
|
|
245
262
|
IdentityService: new IdentityServiceImpl(
|
|
246
|
-
(params) => this.
|
|
263
|
+
(params) => this._createIdentity(params),
|
|
247
264
|
this._serviceContext.identityManager,
|
|
248
265
|
this._serviceContext.keyring,
|
|
249
266
|
),
|
|
@@ -329,4 +346,23 @@ export class ClientServicesHost {
|
|
|
329
346
|
log.trace('dxos.sdk.client-services-host.reset', trace.end({ id: traceId }));
|
|
330
347
|
await this._callbacks?.onReset?.();
|
|
331
348
|
}
|
|
349
|
+
|
|
350
|
+
private async _createIdentity(params?: CreateIdentityOptions) {
|
|
351
|
+
const identity = await this._serviceContext.createIdentity(params);
|
|
352
|
+
|
|
353
|
+
// Setup default space.
|
|
354
|
+
await this._serviceContext.initialized.wait();
|
|
355
|
+
const space = await this._serviceContext.dataSpaceManager!.createSpace();
|
|
356
|
+
const obj: TypedObject = new Properties();
|
|
357
|
+
obj[defaultKey] = identity.identityKey.toHex();
|
|
358
|
+
await this._serviceRegistry.services.DataService!.write({
|
|
359
|
+
spaceKey: space.key,
|
|
360
|
+
batch: {
|
|
361
|
+
objects: [createGenesisMutationFromTypedObject(obj)],
|
|
362
|
+
},
|
|
363
|
+
});
|
|
364
|
+
await this._serviceRegistry.services.DataService!.flush({ spaceKey: space.key });
|
|
365
|
+
|
|
366
|
+
return identity;
|
|
367
|
+
}
|
|
332
368
|
}
|
|
@@ -14,9 +14,9 @@ import { SystemService, SystemStatus } from '@dxos/protocols/proto/dxos/client/s
|
|
|
14
14
|
import { createLinkedPorts, createProtoRpcPeer, createServiceBundle } from '@dxos/rpc';
|
|
15
15
|
import { describe, test } from '@dxos/test';
|
|
16
16
|
|
|
17
|
+
import { ServiceRegistry } from './service-registry';
|
|
17
18
|
import { SystemServiceImpl } from '../system';
|
|
18
19
|
import { createServiceContext } from '../testing';
|
|
19
|
-
import { ServiceRegistry } from './service-registry';
|
|
20
20
|
|
|
21
21
|
// TODO(burdon): Create TestService (that doesn't require peers).
|
|
22
22
|
|
|
@@ -164,7 +164,7 @@ describe('DataSpaceManager', () => {
|
|
|
164
164
|
afterTest(async () => builder.destroy());
|
|
165
165
|
|
|
166
166
|
const peer = builder.createPeer({
|
|
167
|
-
|
|
167
|
+
dataStore: typeof window === 'undefined' ? StorageType.NODE : StorageType.WEBFS,
|
|
168
168
|
});
|
|
169
169
|
await peer.createIdentity();
|
|
170
170
|
await openAndClose(peer.dataSpaceManager);
|
|
@@ -20,9 +20,9 @@ import { Gossip, Presence } from '@dxos/teleport-extension-gossip';
|
|
|
20
20
|
import { Timeframe } from '@dxos/timeframe';
|
|
21
21
|
import { ComplexMap, deferFunction, forEachAsync } from '@dxos/util';
|
|
22
22
|
|
|
23
|
-
import { createAuthProvider } from '../identity';
|
|
24
23
|
import { DataSpace } from './data-space';
|
|
25
24
|
import { spaceGenesis } from './genesis';
|
|
25
|
+
import { createAuthProvider } from '../identity';
|
|
26
26
|
|
|
27
27
|
export interface SigningContext {
|
|
28
28
|
identityKey: PublicKey;
|
|
@@ -7,11 +7,11 @@ import { AUTH_TIMEOUT } from '@dxos/client-protocol';
|
|
|
7
7
|
import { cancelWithContext, Context } from '@dxos/context';
|
|
8
8
|
import { timed } from '@dxos/debug';
|
|
9
9
|
import { MetadataStore, Space, createMappedFeedWriter, DataPipeline } from '@dxos/echo-pipeline';
|
|
10
|
-
import { CancelledError, SystemError } from '@dxos/errors';
|
|
11
10
|
import { FeedStore } from '@dxos/feed-store';
|
|
12
11
|
import { Keyring } from '@dxos/keyring';
|
|
13
12
|
import { PublicKey } from '@dxos/keys';
|
|
14
13
|
import { log } from '@dxos/log';
|
|
14
|
+
import { CancelledError, SystemError } from '@dxos/protocols';
|
|
15
15
|
import { SpaceState, Space as SpaceProto } from '@dxos/protocols/proto/dxos/client/services';
|
|
16
16
|
import { FeedMessage } from '@dxos/protocols/proto/dxos/echo/feed';
|
|
17
17
|
import { SpaceCache } from '@dxos/protocols/proto/dxos/echo/metadata';
|
|
@@ -22,9 +22,9 @@ import { Timeframe } from '@dxos/timeframe';
|
|
|
22
22
|
import { trace } from '@dxos/tracing';
|
|
23
23
|
import { ComplexSet } from '@dxos/util';
|
|
24
24
|
|
|
25
|
-
import { TrustedKeySetAuthVerifier } from '../identity';
|
|
26
25
|
import { SigningContext } from './data-space-manager';
|
|
27
26
|
import { NotarizationPlugin } from './notarization-plugin';
|
|
27
|
+
import { TrustedKeySetAuthVerifier } from '../identity';
|
|
28
28
|
|
|
29
29
|
export type DataSpaceCallbacks = {
|
|
30
30
|
/**
|
|
@@ -101,7 +101,13 @@ export class DataSpace {
|
|
|
101
101
|
this._callbacks = params.callbacks ?? {};
|
|
102
102
|
|
|
103
103
|
this.authVerifier = new TrustedKeySetAuthVerifier({
|
|
104
|
-
trustedKeysProvider: () =>
|
|
104
|
+
trustedKeysProvider: () =>
|
|
105
|
+
new ComplexSet(
|
|
106
|
+
PublicKey.hash,
|
|
107
|
+
Array.from(this._inner.spaceState.members.values())
|
|
108
|
+
.filter((member) => !member.removed)
|
|
109
|
+
.map((member) => member.key),
|
|
110
|
+
),
|
|
105
111
|
update: this._inner.stateUpdate,
|
|
106
112
|
authTimeout: AUTH_TIMEOUT,
|
|
107
113
|
});
|
|
@@ -151,6 +157,7 @@ export class DataSpace {
|
|
|
151
157
|
}
|
|
152
158
|
|
|
153
159
|
private async _open() {
|
|
160
|
+
await this._gossip.open();
|
|
154
161
|
await this._notarizationPlugin.open();
|
|
155
162
|
await this._inner.spaceState.addCredentialProcessor(this._notarizationPlugin);
|
|
156
163
|
await this._inner.open(new Context());
|
|
@@ -180,6 +187,7 @@ export class DataSpace {
|
|
|
180
187
|
await this._notarizationPlugin.close();
|
|
181
188
|
|
|
182
189
|
await this._presence.destroy();
|
|
190
|
+
await this._gossip.close();
|
|
183
191
|
}
|
|
184
192
|
|
|
185
193
|
async postMessage(channel: string, message: any) {
|
|
@@ -11,9 +11,9 @@ import { PublicKey } from '@dxos/keys';
|
|
|
11
11
|
import { Space, SpacesService } from '@dxos/protocols/proto/dxos/client/services';
|
|
12
12
|
import { afterEach, afterTest, beforeEach, describe, test } from '@dxos/test';
|
|
13
13
|
|
|
14
|
+
import { SpacesServiceImpl } from './spaces-service';
|
|
14
15
|
import { ServiceContext } from '../services';
|
|
15
16
|
import { createServiceContext } from '../testing';
|
|
16
|
-
import { SpacesServiceImpl } from './spaces-service';
|
|
17
17
|
|
|
18
18
|
chai.use(chaiAsPromised);
|
|
19
19
|
|
|
@@ -6,10 +6,10 @@ import { EventSubscriptions, UpdateScheduler, scheduleTask } from '@dxos/async';
|
|
|
6
6
|
import { Stream } from '@dxos/codec-protobuf';
|
|
7
7
|
import { CredentialProcessor } from '@dxos/credentials';
|
|
8
8
|
import { raise } from '@dxos/debug';
|
|
9
|
-
import { DataServiceSubscriptions, SpaceManager
|
|
10
|
-
import {
|
|
9
|
+
import { DataServiceSubscriptions, SpaceManager } from '@dxos/echo-pipeline';
|
|
10
|
+
import { invariant } from '@dxos/invariant';
|
|
11
11
|
import { log } from '@dxos/log';
|
|
12
|
-
import { encodeError } from '@dxos/protocols';
|
|
12
|
+
import { ApiError, SpaceNotFoundError, encodeError } from '@dxos/protocols';
|
|
13
13
|
import {
|
|
14
14
|
CreateEpochRequest,
|
|
15
15
|
PostMessageRequest,
|
|
@@ -27,9 +27,9 @@ import { Credential } from '@dxos/protocols/proto/dxos/halo/credentials';
|
|
|
27
27
|
import { GossipMessage } from '@dxos/protocols/proto/dxos/mesh/teleport/gossip';
|
|
28
28
|
import { Provider } from '@dxos/util';
|
|
29
29
|
|
|
30
|
-
import { IdentityManager } from '../identity';
|
|
31
30
|
import { DataSpace } from './data-space';
|
|
32
31
|
import { DataSpaceManager } from './data-space-manager';
|
|
32
|
+
import { IdentityManager } from '../identity';
|
|
33
33
|
|
|
34
34
|
export class SpacesServiceImpl implements SpacesService {
|
|
35
35
|
constructor(
|
|
@@ -99,7 +99,7 @@ export class SpacesServiceImpl implements SpacesService {
|
|
|
99
99
|
subscriptions.add(space.dataPipeline.onNewEpoch.on(ctx, () => scheduler.trigger()));
|
|
100
100
|
|
|
101
101
|
// Pipeline progress.
|
|
102
|
-
space.inner.controlPipeline.state.timeframeUpdate.on(ctx, () => scheduler.trigger());
|
|
102
|
+
subscriptions.add(space.inner.controlPipeline.state.timeframeUpdate.on(ctx, () => scheduler.trigger()));
|
|
103
103
|
if (space.dataPipeline.pipelineState) {
|
|
104
104
|
subscriptions.add(space.dataPipeline.pipelineState.timeframeUpdate.on(ctx, () => scheduler.trigger()));
|
|
105
105
|
}
|
|
@@ -140,8 +140,8 @@ export class SpacesServiceImpl implements SpacesService {
|
|
|
140
140
|
});
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
-
queryCredentials({ spaceKey }: QueryCredentialsRequest): Stream<Credential> {
|
|
144
|
-
return new Stream(({ ctx, next }) => {
|
|
143
|
+
queryCredentials({ spaceKey, noTail }: QueryCredentialsRequest): Stream<Credential> {
|
|
144
|
+
return new Stream(({ ctx, next, close }) => {
|
|
145
145
|
const space = this._spaceManager.spaces.get(spaceKey) ?? raise(new SpaceNotFoundError(spaceKey));
|
|
146
146
|
|
|
147
147
|
const processor: CredentialProcessor = {
|
|
@@ -150,14 +150,31 @@ export class SpacesServiceImpl implements SpacesService {
|
|
|
150
150
|
},
|
|
151
151
|
};
|
|
152
152
|
ctx.onDispose(() => space.spaceState.removeCredentialProcessor(processor));
|
|
153
|
-
scheduleTask(ctx, () =>
|
|
153
|
+
scheduleTask(ctx, async () => {
|
|
154
|
+
await space.spaceState.addCredentialProcessor(processor);
|
|
155
|
+
if (noTail) {
|
|
156
|
+
close();
|
|
157
|
+
}
|
|
158
|
+
});
|
|
154
159
|
});
|
|
155
160
|
}
|
|
156
161
|
|
|
157
162
|
async writeCredentials({ spaceKey, credentials }: WriteCredentialsRequest) {
|
|
158
163
|
const space = this._spaceManager.spaces.get(spaceKey) ?? raise(new SpaceNotFoundError(spaceKey));
|
|
159
164
|
for (const credential of credentials ?? []) {
|
|
160
|
-
|
|
165
|
+
if (credential.proof) {
|
|
166
|
+
await space.controlPipeline.writer.write({ credential: { credential } });
|
|
167
|
+
} else {
|
|
168
|
+
invariant(!credential.id, 'Id on unsigned credentials is not allowed');
|
|
169
|
+
invariant(this._identityManager.identity, 'Identity is not available');
|
|
170
|
+
const signer = this._identityManager.identity.getIdentityCredentialSigner();
|
|
171
|
+
invariant(credential.issuer.equals(signer.getIssuer()));
|
|
172
|
+
const signedCredential = await signer.createCredential({
|
|
173
|
+
subject: credential.subject.id,
|
|
174
|
+
assertion: credential.subject.assertion,
|
|
175
|
+
});
|
|
176
|
+
await space.controlPipeline.writer.write({ credential: { credential: signedCredential } });
|
|
177
|
+
}
|
|
161
178
|
}
|
|
162
179
|
}
|
|
163
180
|
|
|
@@ -202,7 +219,11 @@ export class SpacesServiceImpl implements SpacesService {
|
|
|
202
219
|
displayName: member.assertion.profile?.displayName,
|
|
203
220
|
},
|
|
204
221
|
},
|
|
205
|
-
presence:
|
|
222
|
+
presence: member.removed
|
|
223
|
+
? SpaceMember.PresenceState.REMOVED
|
|
224
|
+
: isMe || peers.length > 0
|
|
225
|
+
? SpaceMember.PresenceState.ONLINE
|
|
226
|
+
: SpaceMember.PresenceState.OFFLINE,
|
|
206
227
|
peerStates: peers,
|
|
207
228
|
};
|
|
208
229
|
}),
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
//
|
|
6
6
|
|
|
7
7
|
import { DX_DATA } from '@dxos/client-protocol';
|
|
8
|
-
import { InvalidConfigError } from '@dxos/
|
|
8
|
+
import { InvalidConfigError } from '@dxos/protocols';
|
|
9
9
|
import { Runtime } from '@dxos/protocols/proto/dxos/config';
|
|
10
10
|
import { createStorage, StorageType } from '@dxos/random-access-storage';
|
|
11
11
|
import { isNode } from '@dxos/util';
|
|
@@ -15,29 +15,29 @@ import StorageDriver = Runtime.Client.Storage.StorageDriver;
|
|
|
15
15
|
// TODO(burdon): Factor out.
|
|
16
16
|
export const createStorageObjects = (config: Runtime.Client.Storage) => {
|
|
17
17
|
const {
|
|
18
|
-
path = isNode() ? DX_DATA : 'dxos/storage', // TODO(burdon): Factor out const.
|
|
19
|
-
storageType,
|
|
20
|
-
keyStorage,
|
|
21
18
|
persistent = false,
|
|
19
|
+
keyStore,
|
|
20
|
+
dataStore,
|
|
21
|
+
dataRoot = isNode() ? DX_DATA : 'dxos/storage', // TODO(burdon): Factor out const.
|
|
22
22
|
} = config ?? {};
|
|
23
23
|
|
|
24
|
-
if (persistent &&
|
|
24
|
+
if (persistent && dataStore === StorageDriver.RAM) {
|
|
25
25
|
throw new InvalidConfigError('RAM storage cannot be used in persistent mode.');
|
|
26
26
|
}
|
|
27
|
-
if (!persistent &&
|
|
27
|
+
if (!persistent && dataStore !== undefined && dataStore !== StorageDriver.RAM) {
|
|
28
28
|
throw new InvalidConfigError('Cannot use a persistent storage in not persistent mode.');
|
|
29
29
|
}
|
|
30
|
-
if (persistent &&
|
|
30
|
+
if (persistent && keyStore === StorageDriver.RAM) {
|
|
31
31
|
throw new InvalidConfigError('RAM key storage cannot be used in persistent mode.');
|
|
32
32
|
}
|
|
33
|
-
if (!persistent &&
|
|
33
|
+
if (!persistent && keyStore !== StorageDriver.RAM && keyStore !== undefined) {
|
|
34
34
|
throw new InvalidConfigError('Cannot use a persistent key storage in not persistent mode.');
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
return {
|
|
38
38
|
storage: createStorage({
|
|
39
|
-
type: persistent ? toStorageType(
|
|
40
|
-
root: `${
|
|
39
|
+
type: persistent ? toStorageType(dataStore) : StorageType.RAM,
|
|
40
|
+
root: `${dataRoot}/`,
|
|
41
41
|
}),
|
|
42
42
|
};
|
|
43
43
|
};
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { Trigger } from '@dxos/async';
|
|
6
|
-
import {
|
|
6
|
+
import { AuthenticatingInvitation, CancellableInvitation } from '@dxos/client-protocol';
|
|
7
7
|
import { invariant } from '@dxos/invariant';
|
|
8
8
|
import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
|
|
9
9
|
|
|
@@ -25,11 +25,11 @@ export const sanitizeInvitation = (invitation: Invitation): Invitation => {
|
|
|
25
25
|
};
|
|
26
26
|
|
|
27
27
|
export type InvitationHost = {
|
|
28
|
-
|
|
28
|
+
share(options?: Partial<Invitation>): CancellableInvitation;
|
|
29
29
|
};
|
|
30
30
|
|
|
31
31
|
export type InvitationGuest = {
|
|
32
|
-
|
|
32
|
+
join(invitation: Invitation | string): AuthenticatingInvitation;
|
|
33
33
|
};
|
|
34
34
|
|
|
35
35
|
export type PerformInvitationCallbacks<T> = {
|
|
@@ -48,8 +48,8 @@ export type PerformInvitationParams = {
|
|
|
48
48
|
guest: ServiceContext | InvitationGuest;
|
|
49
49
|
options?: Partial<Invitation>;
|
|
50
50
|
hooks?: {
|
|
51
|
-
host?: PerformInvitationCallbacks<
|
|
52
|
-
guest?: PerformInvitationCallbacks<
|
|
51
|
+
host?: PerformInvitationCallbacks<CancellableInvitation>;
|
|
52
|
+
guest?: PerformInvitationCallbacks<AuthenticatingInvitation>;
|
|
53
53
|
};
|
|
54
54
|
};
|
|
55
55
|
|
|
@@ -196,7 +196,7 @@ export const performInvitation = ({
|
|
|
196
196
|
const createInvitation = (
|
|
197
197
|
host: ServiceContext | InvitationHost,
|
|
198
198
|
options?: Partial<Invitation>,
|
|
199
|
-
):
|
|
199
|
+
): CancellableInvitation => {
|
|
200
200
|
options ??= {
|
|
201
201
|
authMethod: Invitation.AuthMethod.NONE,
|
|
202
202
|
...(options ?? {}),
|
|
@@ -207,13 +207,13 @@ const createInvitation = (
|
|
|
207
207
|
return host.invitations.createInvitation(hostHandler, options);
|
|
208
208
|
}
|
|
209
209
|
|
|
210
|
-
return host.
|
|
210
|
+
return host.share(options);
|
|
211
211
|
};
|
|
212
212
|
|
|
213
213
|
const acceptInvitation = (
|
|
214
214
|
guest: ServiceContext | InvitationGuest,
|
|
215
215
|
invitation: Invitation,
|
|
216
|
-
):
|
|
216
|
+
): AuthenticatingInvitation => {
|
|
217
217
|
invitation = sanitizeInvitation(invitation);
|
|
218
218
|
|
|
219
219
|
if (guest instanceof ServiceContext) {
|
|
@@ -221,5 +221,5 @@ const acceptInvitation = (
|
|
|
221
221
|
return guest.invitations.acceptInvitation(guestHandler, invitation);
|
|
222
222
|
}
|
|
223
223
|
|
|
224
|
-
return guest.
|
|
224
|
+
return guest.join(invitation);
|
|
225
225
|
};
|
|
@@ -94,7 +94,7 @@ export class TestBuilder {
|
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
export type TestPeerOpts = {
|
|
97
|
-
|
|
97
|
+
dataStore?: StorageType;
|
|
98
98
|
};
|
|
99
99
|
|
|
100
100
|
export type TestPeerProps = {
|
|
@@ -115,7 +115,7 @@ export class TestPeer {
|
|
|
115
115
|
|
|
116
116
|
constructor(
|
|
117
117
|
private readonly signalContext: MemorySignalManagerContext,
|
|
118
|
-
private readonly opts: TestPeerOpts = {
|
|
118
|
+
private readonly opts: TestPeerOpts = { dataStore: StorageType.RAM },
|
|
119
119
|
) {}
|
|
120
120
|
|
|
121
121
|
get props() {
|
|
@@ -123,7 +123,7 @@ export class TestPeer {
|
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
get storage() {
|
|
126
|
-
return (this._props.storage ??= createStorage({ type: this.opts.
|
|
126
|
+
return (this._props.storage ??= createStorage({ type: this.opts.dataStore }));
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
get keyring() {
|
|
@@ -12,9 +12,9 @@ import { createSimplePeerTransportFactory, TransportFactory } from '@dxos/networ
|
|
|
12
12
|
import { RpcPort } from '@dxos/rpc';
|
|
13
13
|
import { getAsyncValue, MaybePromise, Provider } from '@dxos/util';
|
|
14
14
|
|
|
15
|
+
import { ShellRuntimeImpl } from './shell-runtime';
|
|
15
16
|
import { ClientServicesHost } from '../services';
|
|
16
17
|
import { ClientRpcServer, ClientRpcServerParams } from '../services/client-rpc-server';
|
|
17
|
-
import { ShellRuntimeImpl } from './shell-runtime';
|
|
18
18
|
|
|
19
19
|
const LOCK_KEY = 'DXOS_RESOURCE_LOCK';
|
|
20
20
|
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
import { Trigger } from '@dxos/async';
|
|
6
6
|
import { iframeServiceBundle, ShellRuntime, workerServiceBundle, WorkerServiceBundle } from '@dxos/client-protocol';
|
|
7
7
|
import { Config } from '@dxos/config';
|
|
8
|
-
import { RemoteServiceConnectionError } from '@dxos/errors';
|
|
9
8
|
import { log } from '@dxos/log';
|
|
10
9
|
import { SimplePeerTransportService } from '@dxos/network-manager';
|
|
10
|
+
import { RemoteServiceConnectionError } from '@dxos/protocols';
|
|
11
11
|
import { BridgeService } from '@dxos/protocols/proto/dxos/mesh/bridge';
|
|
12
12
|
import { createProtoRpcPeer, ProtoRpcPeer, RpcPort } from '@dxos/rpc';
|
|
13
13
|
import { getAsyncValue, MaybePromise, Provider } from '@dxos/util';
|
|
@@ -33,11 +33,11 @@ export class ShellRuntimeImpl implements ShellRuntime {
|
|
|
33
33
|
return this._spaceKey;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
setLayout(layout
|
|
36
|
+
setLayout({ layout, invitationCode, spaceKey }: LayoutRequest) {
|
|
37
37
|
this._layout = layout;
|
|
38
|
-
this._invitationCode =
|
|
39
|
-
this._spaceKey =
|
|
40
|
-
this.layoutUpdate.emit({ layout,
|
|
38
|
+
this._invitationCode = invitationCode;
|
|
39
|
+
this._spaceKey = spaceKey;
|
|
40
|
+
this.layoutUpdate.emit({ layout, invitationCode, spaceKey });
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
async setAppContext(context: AppContextRequest) {
|