@dxos/client-services 0.1.17 → 0.1.19
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/index.mjs +459 -314
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +497 -352
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/types/src/packlets/deprecated/space.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/authenticator.d.ts +21 -1
- package/dist/types/src/packlets/identity/authenticator.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity-manager.d.ts +3 -9
- package/dist/types/src/packlets/identity/identity-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity.d.ts +5 -4
- package/dist/types/src/packlets/identity/identity.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/halo-invitations-handler.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/space-invitations-handler.d.ts +6 -4
- package/dist/types/src/packlets/invitations/space-invitations-handler.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/space-invitations-service.d.ts +5 -4
- package/dist/types/src/packlets/invitations/space-invitations-service.d.ts.map +1 -1
- package/dist/types/src/packlets/services/service-context.d.ts +3 -1
- package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/data-space-manager.d.ts +28 -0
- package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -0
- package/dist/types/src/packlets/spaces/data-space.d.ts +23 -0
- package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -0
- package/package.json +31 -28
- package/src/packlets/deprecated/space.ts +16 -8
- package/src/packlets/devtools/spaces.ts +1 -1
- package/src/packlets/identity/authenticator.test.ts +8 -3
- package/src/packlets/identity/authenticator.ts +68 -24
- package/src/packlets/identity/identity-manager.test.ts +11 -9
- package/src/packlets/identity/identity-manager.ts +33 -47
- package/src/packlets/identity/identity.test.ts +40 -17
- package/src/packlets/identity/identity.ts +26 -16
- package/src/packlets/invitations/halo-invitations-handler.ts +1 -2
- package/src/packlets/invitations/space-invitations-handler.test.ts +7 -7
- package/src/packlets/invitations/space-invitations-handler.ts +9 -8
- package/src/packlets/invitations/space-invitations-service.test.ts +10 -10
- package/src/packlets/invitations/space-invitations-service.ts +6 -5
- package/src/packlets/services/service-context.ts +21 -21
- package/src/packlets/services/service-host.ts +1 -1
- package/src/packlets/services/service-registry.test.ts +3 -3
- package/src/packlets/spaces/data-space-manager.ts +118 -0
- package/src/packlets/spaces/data-space.ts +66 -0
- package/dist/types/src/packlets/invitations/rpc-extension.d.ts +0 -17
- package/dist/types/src/packlets/invitations/rpc-extension.d.ts.map +0 -1
- package/src/packlets/invitations/rpc-extension.ts +0 -56
|
@@ -7,7 +7,7 @@ import assert from 'node:assert';
|
|
|
7
7
|
import { scheduleTask, sleep, Trigger } from '@dxos/async';
|
|
8
8
|
import { Context } from '@dxos/context';
|
|
9
9
|
import { createAdmissionCredentials, generatePasscode, getCredentialAssertion } from '@dxos/credentials';
|
|
10
|
-
import { SigningContext
|
|
10
|
+
import { SigningContext } from '@dxos/echo-db';
|
|
11
11
|
import { writeMessages } from '@dxos/feed-store';
|
|
12
12
|
import { Keyring } from '@dxos/keyring';
|
|
13
13
|
import { PublicKey } from '@dxos/keys';
|
|
@@ -24,8 +24,10 @@ import {
|
|
|
24
24
|
SpaceAdmissionRequest,
|
|
25
25
|
SpaceHostService
|
|
26
26
|
} from '@dxos/protocols/proto/dxos/halo/invitations';
|
|
27
|
-
import { ExtensionContext } from '@dxos/teleport';
|
|
27
|
+
import { ExtensionContext, RpcExtension } from '@dxos/teleport';
|
|
28
28
|
|
|
29
|
+
import { DataSpace } from '../spaces/data-space';
|
|
30
|
+
import { DataSpaceManager } from '../spaces/data-space-manager';
|
|
29
31
|
import {
|
|
30
32
|
AuthenticatingInvitationProvider,
|
|
31
33
|
AUTHENTICATION_CODE_LENGTH,
|
|
@@ -35,7 +37,6 @@ import {
|
|
|
35
37
|
ON_CLOSE_DELAY
|
|
36
38
|
} from './invitations';
|
|
37
39
|
import { AbstractInvitationsHandler, InvitationsOptions } from './invitations-handler';
|
|
38
|
-
import { RpcExtension } from './rpc-extension';
|
|
39
40
|
|
|
40
41
|
const MAX_OTP_ATTEMPTS = 3;
|
|
41
42
|
|
|
@@ -43,10 +44,10 @@ const MAX_OTP_ATTEMPTS = 3;
|
|
|
43
44
|
* Handles the life-cycle of Space invitations between peers.
|
|
44
45
|
*/
|
|
45
46
|
// TODO(dmaretskyi): Split into Host and Guest parts.
|
|
46
|
-
export class SpaceInvitationsHandler extends AbstractInvitationsHandler<
|
|
47
|
+
export class SpaceInvitationsHandler extends AbstractInvitationsHandler<DataSpace> {
|
|
47
48
|
constructor(
|
|
48
49
|
networkManager: NetworkManager,
|
|
49
|
-
private readonly _spaceManager:
|
|
50
|
+
private readonly _spaceManager: DataSpaceManager,
|
|
50
51
|
private readonly _signingContext: SigningContext,
|
|
51
52
|
private readonly _keyring: Keyring
|
|
52
53
|
) {
|
|
@@ -56,7 +57,7 @@ export class SpaceInvitationsHandler extends AbstractInvitationsHandler<Space> {
|
|
|
56
57
|
/**
|
|
57
58
|
* Creates an invitation and listens for a join request from the invited (guest) peer.
|
|
58
59
|
*/
|
|
59
|
-
createInvitation(space:
|
|
60
|
+
createInvitation(space: DataSpace, options?: InvitationsOptions): CancellableInvitationObservable {
|
|
60
61
|
let swarmConnection: SwarmConnection | undefined;
|
|
61
62
|
const { type, timeout = INVITATION_TIMEOUT, swarmKey } = options ?? {};
|
|
62
63
|
assert(type !== Invitation.Type.OFFLINE);
|
|
@@ -141,7 +142,7 @@ export class SpaceInvitationsHandler extends AbstractInvitationsHandler<Space> {
|
|
|
141
142
|
space.key,
|
|
142
143
|
controlFeedKey,
|
|
143
144
|
dataFeedKey,
|
|
144
|
-
space.genesisFeedKey,
|
|
145
|
+
space.inner.genesisFeedKey,
|
|
145
146
|
guestProfile
|
|
146
147
|
);
|
|
147
148
|
|
|
@@ -150,7 +151,7 @@ export class SpaceInvitationsHandler extends AbstractInvitationsHandler<Space> {
|
|
|
150
151
|
const spaceMemberCredential = credentials[0].credential;
|
|
151
152
|
assert(getCredentialAssertion(spaceMemberCredential)['@type'] === 'dxos.halo.credentials.SpaceMember');
|
|
152
153
|
|
|
153
|
-
await writeMessages(space.controlPipeline.writer, credentials);
|
|
154
|
+
await writeMessages(space.inner.controlPipeline.writer, credentials);
|
|
154
155
|
|
|
155
156
|
// Updating credentials complete.
|
|
156
157
|
complete.wake(deviceKey);
|
|
@@ -24,23 +24,23 @@ describe('services/space-invitation-service', () => {
|
|
|
24
24
|
test('creates space and invites peer', async () => {
|
|
25
25
|
const [host, guest] = await asyncChain<ServiceContext>([createIdentity, closeAfterTest])(createPeers(2));
|
|
26
26
|
|
|
27
|
-
assert(host.
|
|
27
|
+
assert(host.dataSpaceManager);
|
|
28
28
|
assert(host.spaceInvitations);
|
|
29
29
|
const service1: SpaceInvitationsService = new SpaceInvitationsServiceImpl(
|
|
30
30
|
host.identityManager,
|
|
31
31
|
() => host.spaceInvitations!,
|
|
32
|
-
() => host.
|
|
32
|
+
() => host.dataSpaceManager!
|
|
33
33
|
);
|
|
34
34
|
|
|
35
|
-
assert(guest.
|
|
35
|
+
assert(guest.dataSpaceManager);
|
|
36
36
|
assert(guest.spaceInvitations);
|
|
37
37
|
const service2: SpaceInvitationsService = new SpaceInvitationsServiceImpl(
|
|
38
38
|
guest.identityManager,
|
|
39
39
|
() => guest.spaceInvitations!,
|
|
40
|
-
() => guest.
|
|
40
|
+
() => guest.dataSpaceManager!
|
|
41
41
|
);
|
|
42
42
|
|
|
43
|
-
const space1 = await host.
|
|
43
|
+
const space1 = await host.dataSpaceManager.createSpace();
|
|
44
44
|
|
|
45
45
|
const success1 = new Trigger<Invitation>();
|
|
46
46
|
const success2 = new Trigger<Invitation>();
|
|
@@ -85,23 +85,23 @@ describe('services/space-invitation-service', () => {
|
|
|
85
85
|
test('creates space and cancels invitation', async () => {
|
|
86
86
|
const [host, guest] = await asyncChain<ServiceContext>([createIdentity, closeAfterTest])(createPeers(2));
|
|
87
87
|
|
|
88
|
-
assert(host.
|
|
88
|
+
assert(host.dataSpaceManager);
|
|
89
89
|
assert(host.spaceInvitations);
|
|
90
90
|
const service1: SpaceInvitationsService = new SpaceInvitationsServiceImpl(
|
|
91
91
|
host.identityManager,
|
|
92
92
|
() => host.spaceInvitations!,
|
|
93
|
-
() => host.
|
|
93
|
+
() => host.dataSpaceManager!
|
|
94
94
|
);
|
|
95
95
|
|
|
96
|
-
assert(guest.
|
|
96
|
+
assert(guest.dataSpaceManager);
|
|
97
97
|
assert(guest.spaceInvitations);
|
|
98
98
|
const service2: SpaceInvitationsService = new SpaceInvitationsServiceImpl(
|
|
99
99
|
guest.identityManager,
|
|
100
100
|
() => guest.spaceInvitations!,
|
|
101
|
-
() => guest.
|
|
101
|
+
() => guest.dataSpaceManager!
|
|
102
102
|
);
|
|
103
103
|
|
|
104
|
-
const space1 = await host.
|
|
104
|
+
const space1 = await host.dataSpaceManager.createSpace();
|
|
105
105
|
const cancelled = new Trigger();
|
|
106
106
|
|
|
107
107
|
{
|
|
@@ -4,28 +4,29 @@
|
|
|
4
4
|
|
|
5
5
|
import assert from 'node:assert';
|
|
6
6
|
|
|
7
|
-
import { Space, SpaceManager } from '@dxos/echo-db';
|
|
8
7
|
import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
|
|
9
8
|
import { Provider } from '@dxos/util';
|
|
10
9
|
|
|
11
10
|
import { IdentityManager } from '../identity';
|
|
11
|
+
import { DataSpace } from '../spaces/data-space';
|
|
12
|
+
import { DataSpaceManager } from '../spaces/data-space-manager';
|
|
12
13
|
import { InvitationsHandler } from './invitations-handler';
|
|
13
14
|
import { AbstractInvitationsService } from './invitations-service';
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* Adapts invitation service observable to client/service stream.
|
|
17
18
|
*/
|
|
18
|
-
export class SpaceInvitationsServiceImpl extends AbstractInvitationsService<
|
|
19
|
+
export class SpaceInvitationsServiceImpl extends AbstractInvitationsService<DataSpace> {
|
|
19
20
|
// prettier-ignore
|
|
20
21
|
constructor (
|
|
21
22
|
identityManager: IdentityManager,
|
|
22
|
-
private readonly invitationsHandler: Provider<InvitationsHandler<
|
|
23
|
-
private readonly _getSpaceManager: Provider<
|
|
23
|
+
private readonly invitationsHandler: Provider<InvitationsHandler<DataSpace>>,
|
|
24
|
+
private readonly _getSpaceManager: Provider<DataSpaceManager>
|
|
24
25
|
) {
|
|
25
26
|
super(identityManager, invitationsHandler);
|
|
26
27
|
}
|
|
27
28
|
|
|
28
|
-
override getContext(invitation: Invitation):
|
|
29
|
+
override getContext(invitation: Invitation): DataSpace {
|
|
29
30
|
assert(invitation.spaceKey);
|
|
30
31
|
const spaceManager = this._getSpaceManager();
|
|
31
32
|
const space = spaceManager.spaces.get(invitation.spaceKey!);
|
|
@@ -23,6 +23,7 @@ import { Storage } from '@dxos/random-access-storage';
|
|
|
23
23
|
|
|
24
24
|
import { CreateIdentityOptions, IdentityManager } from '../identity';
|
|
25
25
|
import { HaloInvitationsHandler, SpaceInvitationsHandler } from '../invitations';
|
|
26
|
+
import { DataSpaceManager } from '../spaces/data-space-manager';
|
|
26
27
|
|
|
27
28
|
/**
|
|
28
29
|
* Shared backend for all client services.
|
|
@@ -35,11 +36,12 @@ export class ServiceContext {
|
|
|
35
36
|
public readonly metadataStore: MetadataStore;
|
|
36
37
|
public readonly feedStore: FeedStore<FeedMessage>;
|
|
37
38
|
public readonly keyring: Keyring;
|
|
39
|
+
public readonly spaceManager: SpaceManager;
|
|
38
40
|
public readonly identityManager: IdentityManager;
|
|
39
41
|
public readonly haloInvitations: HaloInvitationsHandler;
|
|
40
42
|
|
|
41
43
|
// Initialized after identity is initialized.
|
|
42
|
-
public
|
|
44
|
+
public dataSpaceManager?: DataSpaceManager;
|
|
43
45
|
public spaceInvitations?: SpaceInvitationsHandler;
|
|
44
46
|
|
|
45
47
|
// prettier-ignore
|
|
@@ -60,13 +62,14 @@ export class ServiceContext {
|
|
|
60
62
|
}
|
|
61
63
|
})
|
|
62
64
|
});
|
|
63
|
-
|
|
65
|
+
this.spaceManager = new SpaceManager({
|
|
66
|
+
feedStore: this.feedStore,
|
|
67
|
+
networkManager: this.networkManager
|
|
68
|
+
});
|
|
64
69
|
this.identityManager = new IdentityManager(
|
|
65
70
|
this.metadataStore,
|
|
66
|
-
this.feedStore,
|
|
67
71
|
this.keyring,
|
|
68
|
-
|
|
69
|
-
modelFactory
|
|
72
|
+
this.spaceManager
|
|
70
73
|
);
|
|
71
74
|
|
|
72
75
|
// TODO(burdon): _initialize called in multiple places.
|
|
@@ -76,6 +79,7 @@ export class ServiceContext {
|
|
|
76
79
|
|
|
77
80
|
async open() {
|
|
78
81
|
log('opening...');
|
|
82
|
+
await this.spaceManager.open();
|
|
79
83
|
await this.identityManager.open();
|
|
80
84
|
if (this.identityManager.identity) {
|
|
81
85
|
await this._initialize();
|
|
@@ -85,8 +89,9 @@ export class ServiceContext {
|
|
|
85
89
|
|
|
86
90
|
async close() {
|
|
87
91
|
log('closing...');
|
|
92
|
+
await this.dataSpaceManager?.close();
|
|
88
93
|
await this.identityManager.close();
|
|
89
|
-
await this.spaceManager
|
|
94
|
+
await this.spaceManager.close();
|
|
90
95
|
await this.feedStore.close();
|
|
91
96
|
await this.networkManager.close();
|
|
92
97
|
this.dataServiceSubscriptions.clear();
|
|
@@ -103,7 +108,6 @@ export class ServiceContext {
|
|
|
103
108
|
async createIdentity(params: CreateIdentityOptions = {}) {
|
|
104
109
|
const identity = await this.identityManager.createIdentity(params);
|
|
105
110
|
|
|
106
|
-
this.dataServiceSubscriptions.registerSpace(identity.haloSpaceKey, identity.haloDatabase.createDataServiceHost());
|
|
107
111
|
await this._initialize();
|
|
108
112
|
return identity;
|
|
109
113
|
}
|
|
@@ -120,22 +124,18 @@ export class ServiceContext {
|
|
|
120
124
|
profile: identity.profileDocument
|
|
121
125
|
};
|
|
122
126
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
await spaceManager.open();
|
|
135
|
-
this.spaceManager = spaceManager;
|
|
127
|
+
this.dataSpaceManager = new DataSpaceManager(
|
|
128
|
+
this.spaceManager,
|
|
129
|
+
this.metadataStore,
|
|
130
|
+
this.dataServiceSubscriptions,
|
|
131
|
+
this.keyring,
|
|
132
|
+
signingContext,
|
|
133
|
+
this.modelFactory
|
|
134
|
+
);
|
|
135
|
+
await this.dataSpaceManager.open();
|
|
136
136
|
this.spaceInvitations = new SpaceInvitationsHandler(
|
|
137
137
|
this.networkManager,
|
|
138
|
-
this.
|
|
138
|
+
this.dataSpaceManager,
|
|
139
139
|
signingContext,
|
|
140
140
|
this.keyring
|
|
141
141
|
);
|
|
@@ -99,7 +99,7 @@ export class ClientServicesHost implements ClientServicesProvider {
|
|
|
99
99
|
SpaceInvitationsService: new SpaceInvitationsServiceImpl(
|
|
100
100
|
this._serviceContext.identityManager,
|
|
101
101
|
() => this._serviceContext.spaceInvitations ?? raise(new Error('SpaceInvitations not initialized')),
|
|
102
|
-
() => this._serviceContext.
|
|
102
|
+
() => this._serviceContext.dataSpaceManager ?? raise(new Error('SpaceManager not initialized'))
|
|
103
103
|
),
|
|
104
104
|
|
|
105
105
|
SpacesService: new SpacesServiceImpl(),
|
|
@@ -31,15 +31,15 @@ describe('service registry', () => {
|
|
|
31
31
|
await serviceContext.open();
|
|
32
32
|
await serviceContext.createIdentity();
|
|
33
33
|
|
|
34
|
-
assert(serviceContext.
|
|
34
|
+
assert(serviceContext.dataSpaceManager);
|
|
35
35
|
assert(serviceContext.spaceInvitations);
|
|
36
|
-
const space = await serviceContext.
|
|
36
|
+
const space = await serviceContext.dataSpaceManager.createSpace();
|
|
37
37
|
|
|
38
38
|
const serviceRegistry = new ServiceRegistry(serviceBundle, {
|
|
39
39
|
SpaceInvitationsService: new SpaceInvitationsServiceImpl(
|
|
40
40
|
serviceContext.identityManager,
|
|
41
41
|
() => serviceContext.spaceInvitations!,
|
|
42
|
-
() => serviceContext.
|
|
42
|
+
() => serviceContext.dataSpaceManager!
|
|
43
43
|
)
|
|
44
44
|
});
|
|
45
45
|
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2022 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { Event, synchronized } from '@dxos/async';
|
|
6
|
+
import {
|
|
7
|
+
AcceptSpaceOptions,
|
|
8
|
+
DataServiceSubscriptions,
|
|
9
|
+
MetadataStore,
|
|
10
|
+
SigningContext,
|
|
11
|
+
Space,
|
|
12
|
+
SpaceManager,
|
|
13
|
+
spaceGenesis
|
|
14
|
+
} from '@dxos/echo-db';
|
|
15
|
+
import { Keyring } from '@dxos/keyring';
|
|
16
|
+
import { PublicKey } from '@dxos/keys';
|
|
17
|
+
import { log } from '@dxos/log';
|
|
18
|
+
import { ModelFactory } from '@dxos/model-factory';
|
|
19
|
+
import { SpaceMetadata } from '@dxos/protocols/proto/dxos/echo/metadata';
|
|
20
|
+
import { Presence } from '@dxos/teleport-extension-presence';
|
|
21
|
+
import { ComplexMap } from '@dxos/util';
|
|
22
|
+
|
|
23
|
+
import { DataSpace } from './data-space';
|
|
24
|
+
|
|
25
|
+
export class DataSpaceManager {
|
|
26
|
+
public readonly updated = new Event();
|
|
27
|
+
|
|
28
|
+
private readonly _spaces = new ComplexMap<PublicKey, DataSpace>(PublicKey.hash);
|
|
29
|
+
|
|
30
|
+
constructor(
|
|
31
|
+
private readonly _spaceManager: SpaceManager,
|
|
32
|
+
private readonly _metadataStore: MetadataStore,
|
|
33
|
+
private readonly _dataServiceSubscriptions: DataServiceSubscriptions,
|
|
34
|
+
private readonly _keyring: Keyring,
|
|
35
|
+
private readonly _signingContext: SigningContext,
|
|
36
|
+
private readonly _modelFactory: ModelFactory
|
|
37
|
+
) {}
|
|
38
|
+
|
|
39
|
+
// TODO(burdon): Remove.
|
|
40
|
+
get spaces() {
|
|
41
|
+
return this._spaces;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@synchronized
|
|
45
|
+
async open() {
|
|
46
|
+
await this._metadataStore.load();
|
|
47
|
+
|
|
48
|
+
for (const spaceMetadata of this._metadataStore.spaces) {
|
|
49
|
+
await this._constructSpace(spaceMetadata);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
@synchronized
|
|
54
|
+
async close() {}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Creates a new space writing the genesis credentials to the control feed.
|
|
58
|
+
*/
|
|
59
|
+
async createSpace() {
|
|
60
|
+
const spaceKey = await this._keyring.createKey();
|
|
61
|
+
const controlFeedKey = await this._keyring.createKey();
|
|
62
|
+
const dataFeedKey = await this._keyring.createKey();
|
|
63
|
+
const metadata: SpaceMetadata = {
|
|
64
|
+
key: spaceKey,
|
|
65
|
+
genesisFeedKey: controlFeedKey,
|
|
66
|
+
controlFeedKey,
|
|
67
|
+
dataFeedKey
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
log('creating space...', { spaceKey });
|
|
71
|
+
const space = await this._constructSpace(metadata);
|
|
72
|
+
|
|
73
|
+
await spaceGenesis(this._keyring, this._signingContext, space.inner);
|
|
74
|
+
await this._metadataStore.addSpace(metadata);
|
|
75
|
+
|
|
76
|
+
this.updated.emit();
|
|
77
|
+
return space;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// TODO(burdon): Rename join space.
|
|
81
|
+
async acceptSpace(opts: AcceptSpaceOptions): Promise<DataSpace> {
|
|
82
|
+
const metadata: SpaceMetadata = {
|
|
83
|
+
key: opts.spaceKey,
|
|
84
|
+
genesisFeedKey: opts.genesisFeedKey,
|
|
85
|
+
controlFeedKey: opts.controlFeedKey,
|
|
86
|
+
dataFeedKey: opts.dataFeedKey
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const space = await this._constructSpace(metadata);
|
|
90
|
+
await this._metadataStore.addSpace(metadata);
|
|
91
|
+
this.updated.emit();
|
|
92
|
+
return space;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
private async _constructSpace(metadata: SpaceMetadata) {
|
|
96
|
+
const presence = new Presence({
|
|
97
|
+
localPeerId: this._signingContext.deviceKey,
|
|
98
|
+
announceInterval: 1_000,
|
|
99
|
+
offlineTimeout: 30_000,
|
|
100
|
+
identityKey: this._signingContext.identityKey
|
|
101
|
+
});
|
|
102
|
+
const space: Space = await this._spaceManager.constructSpace({
|
|
103
|
+
metadata,
|
|
104
|
+
swarmIdentity: {
|
|
105
|
+
peerKey: this._signingContext.deviceKey,
|
|
106
|
+
credentialProvider: this._signingContext.credentialProvider,
|
|
107
|
+
credentialAuthenticator: this._signingContext.credentialAuthenticator
|
|
108
|
+
},
|
|
109
|
+
dataPipelineControllerProvider: () => dataSpace.dataPipelineController,
|
|
110
|
+
presence
|
|
111
|
+
});
|
|
112
|
+
const dataSpace = new DataSpace(space, this._modelFactory, this._signingContext.identityKey, presence);
|
|
113
|
+
await space.open();
|
|
114
|
+
this._dataServiceSubscriptions.registerSpace(space.key, dataSpace.database.createDataServiceHost());
|
|
115
|
+
this._spaces.set(metadata.key, dataSpace);
|
|
116
|
+
return dataSpace;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2022 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import assert from 'node:assert';
|
|
6
|
+
|
|
7
|
+
import { Context } from '@dxos/context';
|
|
8
|
+
import { Database, DataPipelineControllerImpl, ISpace, Space } from '@dxos/echo-db';
|
|
9
|
+
import { PublicKey } from '@dxos/keys';
|
|
10
|
+
import { ModelFactory } from '@dxos/model-factory';
|
|
11
|
+
import { Presence } from '@dxos/teleport-extension-presence';
|
|
12
|
+
|
|
13
|
+
export class DataSpace implements ISpace {
|
|
14
|
+
private readonly _ctx = new Context();
|
|
15
|
+
private readonly _dataPipelineController: DataPipelineControllerImpl;
|
|
16
|
+
|
|
17
|
+
constructor(
|
|
18
|
+
private readonly _inner: Space,
|
|
19
|
+
private readonly _modelFactory: ModelFactory,
|
|
20
|
+
private readonly _memberKey: PublicKey,
|
|
21
|
+
private readonly _presence: Presence
|
|
22
|
+
) {
|
|
23
|
+
this._dataPipelineController = new DataPipelineControllerImpl(_modelFactory, _memberKey, (feedKey) =>
|
|
24
|
+
_inner.spaceState.feeds.get(feedKey)
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
get key() {
|
|
29
|
+
return this._inner.key;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
get inner() {
|
|
33
|
+
return this._inner;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
get isOpen() {
|
|
37
|
+
return this._inner.isOpen;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
get dataPipelineController(): DataPipelineControllerImpl {
|
|
41
|
+
return this._dataPipelineController;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
get database(): Database {
|
|
45
|
+
assert(this._dataPipelineController.database);
|
|
46
|
+
return this._dataPipelineController.database;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
get stateUpdate() {
|
|
50
|
+
return this._inner.stateUpdate;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
get presence() {
|
|
54
|
+
return this._presence;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async open() {
|
|
58
|
+
await this._inner.open();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async close() {
|
|
62
|
+
await this._ctx.dispose();
|
|
63
|
+
await this._inner.close();
|
|
64
|
+
await this._presence.destroy();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { ProtoRpcPeerOptions } from '@dxos/rpc';
|
|
2
|
-
import { ExtensionContext, TeleportExtension } from '@dxos/teleport';
|
|
3
|
-
export declare abstract class RpcExtension<Client, Server> implements TeleportExtension {
|
|
4
|
-
private readonly _params;
|
|
5
|
-
private _extensionContext;
|
|
6
|
-
private _rpc;
|
|
7
|
-
constructor(_params: Omit<ProtoRpcPeerOptions<Client, Server>, 'port' | 'handlers'>);
|
|
8
|
-
get initiator(): boolean;
|
|
9
|
-
get localPeerId(): import("@dxos/keys").PublicKey;
|
|
10
|
-
get remotePeerId(): import("@dxos/keys").PublicKey;
|
|
11
|
-
get rpc(): Client;
|
|
12
|
-
protected abstract getHandlers(): Promise<Server>;
|
|
13
|
-
onOpen(context: ExtensionContext): Promise<void>;
|
|
14
|
-
onClose(err?: Error | undefined): Promise<void>;
|
|
15
|
-
close(): void;
|
|
16
|
-
}
|
|
17
|
-
//# sourceMappingURL=rpc-extension.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rpc-extension.d.ts","sourceRoot":"","sources":["../../../../../src/packlets/invitations/rpc-extension.ts"],"names":[],"mappings":"AAIA,OAAO,EAAoC,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAClF,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAErE,8BAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,CAAE,YAAW,iBAAiB;IAIjE,OAAO,CAAC,QAAQ,CAAC,OAAO;IAHpC,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,IAAI,CAAwB;gBAEP,OAAO,EAAE,IAAI,CAAC,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;IAEpG,IAAI,SAAS,YAEZ;IAED,IAAI,WAAW,mCAEd;IAED,IAAI,YAAY,mCAEf;IAED,IAAI,GAAG,IAAI,MAAM,CAEhB;IAED,SAAS,CAAC,QAAQ,CAAC,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC;IAE3C,MAAM,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBhD,OAAO,CAAC,GAAG,CAAC,EAAE,KAAK,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrD,KAAK;CAGN"}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2022 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { createProtoRpcPeer, ProtoRpcPeer, ProtoRpcPeerOptions } from '@dxos/rpc';
|
|
6
|
-
import { ExtensionContext, TeleportExtension } from '@dxos/teleport';
|
|
7
|
-
|
|
8
|
-
export abstract class RpcExtension<Client, Server> implements TeleportExtension {
|
|
9
|
-
private _extensionContext!: ExtensionContext;
|
|
10
|
-
private _rpc!: ProtoRpcPeer<Client>;
|
|
11
|
-
|
|
12
|
-
constructor(private readonly _params: Omit<ProtoRpcPeerOptions<Client, Server>, 'port' | 'handlers'>) {}
|
|
13
|
-
|
|
14
|
-
get initiator() {
|
|
15
|
-
return this._extensionContext.initiator;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
get localPeerId() {
|
|
19
|
-
return this._extensionContext.localPeerId;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
get remotePeerId() {
|
|
23
|
-
return this._extensionContext.remotePeerId;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
get rpc(): Client {
|
|
27
|
-
return this._rpc.rpc;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
protected abstract getHandlers(): Promise<Server>;
|
|
31
|
-
|
|
32
|
-
async onOpen(context: ExtensionContext): Promise<void> {
|
|
33
|
-
this._extensionContext = context;
|
|
34
|
-
|
|
35
|
-
const handlers = await this.getHandlers();
|
|
36
|
-
|
|
37
|
-
const port = context.createPort('rpc', {
|
|
38
|
-
contentType: 'application/x-protobuf; messageType="dxos.rpc.Message"'
|
|
39
|
-
});
|
|
40
|
-
this._rpc = createProtoRpcPeer({
|
|
41
|
-
...this._params,
|
|
42
|
-
handlers,
|
|
43
|
-
port
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
await this._rpc.open();
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
async onClose(err?: Error | undefined): Promise<void> {
|
|
50
|
-
await this._rpc.close();
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
close() {
|
|
54
|
-
this._extensionContext.close();
|
|
55
|
-
}
|
|
56
|
-
}
|