@dxos/client-services 0.1.0
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/LICENSE +21 -0
- package/README.md +20 -0
- package/dist/src/errors.d.ts +8 -0
- package/dist/src/errors.d.ts.map +1 -0
- package/dist/src/errors.js +21 -0
- package/dist/src/errors.js.map +1 -0
- package/dist/src/index.d.ts +7 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +26 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/packlets/devtools/devtools-host-events.d.ts +5 -0
- package/dist/src/packlets/devtools/devtools-host-events.d.ts.map +1 -0
- package/dist/src/packlets/devtools/devtools-host-events.js +14 -0
- package/dist/src/packlets/devtools/devtools-host-events.js.map +1 -0
- package/dist/src/packlets/devtools/feeds.d.ts +11 -0
- package/dist/src/packlets/devtools/feeds.d.ts.map +1 -0
- package/dist/src/packlets/devtools/feeds.js +72 -0
- package/dist/src/packlets/devtools/feeds.js.map +1 -0
- package/dist/src/packlets/devtools/index.d.ts +5 -0
- package/dist/src/packlets/devtools/index.d.ts.map +1 -0
- package/dist/src/packlets/devtools/index.js +24 -0
- package/dist/src/packlets/devtools/index.js.map +1 -0
- package/dist/src/packlets/devtools/network.d.ts +19 -0
- package/dist/src/packlets/devtools/network.d.ts.map +1 -0
- package/dist/src/packlets/devtools/network.js +79 -0
- package/dist/src/packlets/devtools/network.js.map +1 -0
- package/dist/src/packlets/devtools/spaces.d.ts +5 -0
- package/dist/src/packlets/devtools/spaces.d.ts.map +1 -0
- package/dist/src/packlets/devtools/spaces.js +38 -0
- package/dist/src/packlets/devtools/spaces.js.map +1 -0
- package/dist/src/packlets/identity/authenticator.d.ts +7 -0
- package/dist/src/packlets/identity/authenticator.d.ts.map +1 -0
- package/dist/src/packlets/identity/authenticator.js +40 -0
- package/dist/src/packlets/identity/authenticator.js.map +1 -0
- package/dist/src/packlets/identity/authenticator.test.d.ts +2 -0
- package/dist/src/packlets/identity/authenticator.test.d.ts.map +1 -0
- package/dist/src/packlets/identity/authenticator.test.js +32 -0
- package/dist/src/packlets/identity/authenticator.test.js.map +1 -0
- package/dist/src/packlets/identity/identity-manager.d.ts +35 -0
- package/dist/src/packlets/identity/identity-manager.d.ts.map +1 -0
- package/dist/src/packlets/identity/identity-manager.js +151 -0
- package/dist/src/packlets/identity/identity-manager.js.map +1 -0
- package/dist/src/packlets/identity/identity-manager.test.d.ts +2 -0
- package/dist/src/packlets/identity/identity-manager.test.d.ts.map +1 -0
- package/dist/src/packlets/identity/identity-manager.test.js +92 -0
- package/dist/src/packlets/identity/identity-manager.test.js.map +1 -0
- package/dist/src/packlets/identity/identity.d.ts +43 -0
- package/dist/src/packlets/identity/identity.d.ts.map +1 -0
- package/dist/src/packlets/identity/identity.js +74 -0
- package/dist/src/packlets/identity/identity.js.map +1 -0
- package/dist/src/packlets/identity/identity.test.d.ts +2 -0
- package/dist/src/packlets/identity/identity.test.d.ts.map +1 -0
- package/dist/src/packlets/identity/identity.test.js +258 -0
- package/dist/src/packlets/identity/identity.test.js.map +1 -0
- package/dist/src/packlets/identity/index.d.ts +4 -0
- package/dist/src/packlets/identity/index.d.ts.map +1 -0
- package/dist/src/packlets/identity/index.js +23 -0
- package/dist/src/packlets/identity/index.js.map +1 -0
- package/dist/src/packlets/invitations/common.d.ts +35 -0
- package/dist/src/packlets/invitations/common.d.ts.map +1 -0
- package/dist/src/packlets/invitations/common.js +12 -0
- package/dist/src/packlets/invitations/common.js.map +1 -0
- package/dist/src/packlets/invitations/halo-invitations.d.ts +23 -0
- package/dist/src/packlets/invitations/halo-invitations.d.ts.map +1 -0
- package/dist/src/packlets/invitations/halo-invitations.js +150 -0
- package/dist/src/packlets/invitations/halo-invitations.js.map +1 -0
- package/dist/src/packlets/invitations/index.d.ts +5 -0
- package/dist/src/packlets/invitations/index.d.ts.map +1 -0
- package/dist/src/packlets/invitations/index.js +24 -0
- package/dist/src/packlets/invitations/index.js.map +1 -0
- package/dist/src/packlets/invitations/invitation-wrapper.d.ts +36 -0
- package/dist/src/packlets/invitations/invitation-wrapper.d.ts.map +1 -0
- package/dist/src/packlets/invitations/invitation-wrapper.js +104 -0
- package/dist/src/packlets/invitations/invitation-wrapper.js.map +1 -0
- package/dist/src/packlets/invitations/observable.test.d.ts +2 -0
- package/dist/src/packlets/invitations/observable.test.d.ts.map +1 -0
- package/dist/src/packlets/invitations/observable.test.js +43 -0
- package/dist/src/packlets/invitations/observable.test.js.map +1 -0
- package/dist/src/packlets/invitations/space-invitations.d.ts +25 -0
- package/dist/src/packlets/invitations/space-invitations.d.ts.map +1 -0
- package/dist/src/packlets/invitations/space-invitations.js +136 -0
- package/dist/src/packlets/invitations/space-invitations.js.map +1 -0
- package/dist/src/packlets/services/impl/devtools.d.ts +34 -0
- package/dist/src/packlets/services/impl/devtools.d.ts.map +1 -0
- package/dist/src/packlets/services/impl/devtools.js +77 -0
- package/dist/src/packlets/services/impl/devtools.js.map +1 -0
- package/dist/src/packlets/services/impl/halo.d.ts +20 -0
- package/dist/src/packlets/services/impl/halo.d.ts.map +1 -0
- package/dist/src/packlets/services/impl/halo.js +93 -0
- package/dist/src/packlets/services/impl/halo.js.map +1 -0
- package/dist/src/packlets/services/impl/index.d.ts +6 -0
- package/dist/src/packlets/services/impl/index.d.ts.map +1 -0
- package/dist/src/packlets/services/impl/index.js +26 -0
- package/dist/src/packlets/services/impl/index.js.map +1 -0
- package/dist/src/packlets/services/impl/party.d.ts +25 -0
- package/dist/src/packlets/services/impl/party.d.ts.map +1 -0
- package/dist/src/packlets/services/impl/party.js +265 -0
- package/dist/src/packlets/services/impl/party.js.map +1 -0
- package/dist/src/packlets/services/impl/profile.d.ts +19 -0
- package/dist/src/packlets/services/impl/profile.d.ts.map +1 -0
- package/dist/src/packlets/services/impl/profile.js +120 -0
- package/dist/src/packlets/services/impl/profile.js.map +1 -0
- package/dist/src/packlets/services/impl/system.d.ts +9 -0
- package/dist/src/packlets/services/impl/system.d.ts.map +1 -0
- package/dist/src/packlets/services/impl/system.js +20 -0
- package/dist/src/packlets/services/impl/system.js.map +1 -0
- package/dist/src/packlets/services/impl/tracing.d.ts +12 -0
- package/dist/src/packlets/services/impl/tracing.d.ts.map +1 -0
- package/dist/src/packlets/services/impl/tracing.js +22 -0
- package/dist/src/packlets/services/impl/tracing.js.map +1 -0
- package/dist/src/packlets/services/index.d.ts +6 -0
- package/dist/src/packlets/services/index.d.ts.map +1 -0
- package/dist/src/packlets/services/index.js +25 -0
- package/dist/src/packlets/services/index.js.map +1 -0
- package/dist/src/packlets/services/service-context.d.ts +36 -0
- package/dist/src/packlets/services/service-context.d.ts.map +1 -0
- package/dist/src/packlets/services/service-context.js +112 -0
- package/dist/src/packlets/services/service-context.js.map +1 -0
- package/dist/src/packlets/services/service-factory.d.ts +15 -0
- package/dist/src/packlets/services/service-factory.d.ts.map +1 -0
- package/dist/src/packlets/services/service-factory.js +25 -0
- package/dist/src/packlets/services/service-factory.js.map +1 -0
- package/dist/src/packlets/services/service-host.d.ts +27 -0
- package/dist/src/packlets/services/service-host.d.ts.map +1 -0
- package/dist/src/packlets/services/service-host.js +78 -0
- package/dist/src/packlets/services/service-host.js.map +1 -0
- package/dist/src/packlets/services/service-host.test.d.ts +2 -0
- package/dist/src/packlets/services/service-host.test.d.ts.map +1 -0
- package/dist/src/packlets/services/service-host.test.js +78 -0
- package/dist/src/packlets/services/service-host.test.js.map +1 -0
- package/dist/src/packlets/services/services.d.ts +19 -0
- package/dist/src/packlets/services/services.d.ts.map +1 -0
- package/dist/src/packlets/services/services.js +19 -0
- package/dist/src/packlets/services/services.js.map +1 -0
- package/dist/src/packlets/services/signer.d.ts +9 -0
- package/dist/src/packlets/services/signer.d.ts.map +1 -0
- package/dist/src/packlets/services/signer.js +6 -0
- package/dist/src/packlets/services/signer.js.map +1 -0
- package/dist/src/packlets/services/testing/halo.test.d.ts +2 -0
- package/dist/src/packlets/services/testing/halo.test.d.ts.map +1 -0
- package/dist/src/packlets/services/testing/halo.test.js +34 -0
- package/dist/src/packlets/services/testing/halo.test.js.map +1 -0
- package/dist/src/packlets/services/testing/spaces.test.d.ts +2 -0
- package/dist/src/packlets/services/testing/spaces.test.d.ts.map +1 -0
- package/dist/src/packlets/services/testing/spaces.test.js +68 -0
- package/dist/src/packlets/services/testing/spaces.test.js.map +1 -0
- package/dist/src/packlets/services/testing/testing.d.ts +8 -0
- package/dist/src/packlets/services/testing/testing.d.ts.map +1 -0
- package/dist/src/packlets/services/testing/testing.js +23 -0
- package/dist/src/packlets/services/testing/testing.js.map +1 -0
- package/dist/src/packlets/storage/index.d.ts +2 -0
- package/dist/src/packlets/storage/index.d.ts.map +1 -0
- package/dist/src/packlets/storage/index.js +21 -0
- package/dist/src/packlets/storage/index.js.map +1 -0
- package/dist/src/packlets/storage/storage.d.ts +7 -0
- package/dist/src/packlets/storage/storage.d.ts.map +1 -0
- package/dist/src/packlets/storage/storage.js +89 -0
- package/dist/src/packlets/storage/storage.js.map +1 -0
- package/package.json +61 -0
- package/src/errors.ts +19 -0
- package/src/index.ts +11 -0
- package/src/packlets/devtools/devtools-host-events.ts +8 -0
- package/src/packlets/devtools/feeds.ts +91 -0
- package/src/packlets/devtools/index.ts +8 -0
- package/src/packlets/devtools/network.ts +89 -0
- package/src/packlets/devtools/spaces.ts +50 -0
- package/src/packlets/identity/authenticator.test.ts +32 -0
- package/src/packlets/identity/authenticator.ts +49 -0
- package/src/packlets/identity/identity-manager.test.ts +121 -0
- package/src/packlets/identity/identity-manager.ts +207 -0
- package/src/packlets/identity/identity.test.ts +295 -0
- package/src/packlets/identity/identity.ts +109 -0
- package/src/packlets/identity/index.ts +7 -0
- package/src/packlets/invitations/common.ts +48 -0
- package/src/packlets/invitations/halo-invitations.ts +162 -0
- package/src/packlets/invitations/index.ts +8 -0
- package/src/packlets/invitations/invitation-wrapper.ts +140 -0
- package/src/packlets/invitations/observable.test.ts +67 -0
- package/src/packlets/invitations/space-invitations.ts +159 -0
- package/src/packlets/services/impl/devtools.ts +141 -0
- package/src/packlets/services/impl/halo.ts +107 -0
- package/src/packlets/services/impl/index.ts +11 -0
- package/src/packlets/services/impl/party.ts +305 -0
- package/src/packlets/services/impl/profile.ts +141 -0
- package/src/packlets/services/impl/system.ts +19 -0
- package/src/packlets/services/impl/tracing.ts +21 -0
- package/src/packlets/services/index.ts +9 -0
- package/src/packlets/services/service-context.ts +151 -0
- package/src/packlets/services/service-factory.ts +35 -0
- package/src/packlets/services/service-host.test.ts +88 -0
- package/src/packlets/services/service-host.ts +101 -0
- package/src/packlets/services/services.ts +39 -0
- package/src/packlets/services/signer.ts +13 -0
- package/src/packlets/services/testing/halo.test.ts +40 -0
- package/src/packlets/services/testing/spaces.test.ts +87 -0
- package/src/packlets/services/testing/testing.ts +28 -0
- package/src/packlets/storage/index.ts +5 -0
- package/src/packlets/storage/storage.ts +97 -0
- package/src/typings.d.ts +5 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2022 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { Stream } from '@dxos/codec-protobuf';
|
|
6
|
+
import { Config } from '@dxos/config';
|
|
7
|
+
import { todo } from '@dxos/debug';
|
|
8
|
+
import {
|
|
9
|
+
ClearSnapshotsRequest,
|
|
10
|
+
DevtoolsHost,
|
|
11
|
+
EnableDebugLoggingRequest,
|
|
12
|
+
EnableDebugLoggingResponse,
|
|
13
|
+
Event,
|
|
14
|
+
GetConfigResponse,
|
|
15
|
+
GetNetworkPeersRequest,
|
|
16
|
+
GetNetworkPeersResponse,
|
|
17
|
+
GetPartySnapshotRequest,
|
|
18
|
+
GetPartySnapshotResponse,
|
|
19
|
+
ResetStorageRequest,
|
|
20
|
+
SavePartySnapshotRequest,
|
|
21
|
+
SavePartySnapshotResponse,
|
|
22
|
+
SubscribeToCredentialMessagesRequest,
|
|
23
|
+
SubscribeToCredentialMessagesResponse,
|
|
24
|
+
SubscribeToFeedBlocksRequest,
|
|
25
|
+
SubscribeToFeedBlocksResponse,
|
|
26
|
+
SubscribeToFeedsRequest,
|
|
27
|
+
SubscribeToFeedsResponse,
|
|
28
|
+
SubscribeToItemsRequest,
|
|
29
|
+
SubscribeToItemsResponse,
|
|
30
|
+
SubscribeToKeyringKeysRequest,
|
|
31
|
+
SubscribeToKeyringKeysResponse,
|
|
32
|
+
SubscribeToNetworkTopicsResponse,
|
|
33
|
+
SubscribeToPartiesRequest,
|
|
34
|
+
SubscribeToPartiesResponse,
|
|
35
|
+
SubscribeToSignalStatusResponse,
|
|
36
|
+
SubscribeToSignalTraceResponse,
|
|
37
|
+
SubscribeToSwarmInfoResponse
|
|
38
|
+
} from '@dxos/protocols/proto/dxos/devtools/host';
|
|
39
|
+
|
|
40
|
+
import {
|
|
41
|
+
DevtoolsHostEvents,
|
|
42
|
+
subscribeToNetworkStatus,
|
|
43
|
+
subscribeToSignalTrace,
|
|
44
|
+
subscribeToSwarmInfo,
|
|
45
|
+
subscribeToSpaces,
|
|
46
|
+
subscribeToFeedBlocks,
|
|
47
|
+
subscribeToFeeds
|
|
48
|
+
} from '../../devtools';
|
|
49
|
+
import { ServiceContext } from '../service-context';
|
|
50
|
+
|
|
51
|
+
export type DevtoolsServiceParams = {
|
|
52
|
+
events: DevtoolsHostEvents;
|
|
53
|
+
config: Config;
|
|
54
|
+
context: ServiceContext;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export class DevtoolsService implements DevtoolsHost {
|
|
58
|
+
constructor(private readonly params: DevtoolsServiceParams) {}
|
|
59
|
+
|
|
60
|
+
events(request: void): Stream<Event> {
|
|
61
|
+
return new Stream<Event>(({ next }) => {
|
|
62
|
+
this.params.events.ready.on(() => {
|
|
63
|
+
next({ ready: {} });
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
getConfig(request: void): Promise<GetConfigResponse> {
|
|
69
|
+
todo();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
resetStorage(request: ResetStorageRequest): Promise<void> {
|
|
73
|
+
todo();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
enableDebugLogging(request: EnableDebugLoggingRequest): Promise<EnableDebugLoggingResponse> {
|
|
77
|
+
todo();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
disableDebugLogging(request: EnableDebugLoggingRequest): Promise<EnableDebugLoggingResponse> {
|
|
81
|
+
todo();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
subscribeToKeyringKeys(request: SubscribeToKeyringKeysRequest): Stream<SubscribeToKeyringKeysResponse> {
|
|
85
|
+
todo();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
subscribeToCredentialMessages(
|
|
89
|
+
request: SubscribeToCredentialMessagesRequest
|
|
90
|
+
): Stream<SubscribeToCredentialMessagesResponse> {
|
|
91
|
+
todo();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
subscribeToParties(request: SubscribeToPartiesRequest): Stream<SubscribeToPartiesResponse> {
|
|
95
|
+
return subscribeToSpaces(this.params.context, request);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
subscribeToItems(request: SubscribeToItemsRequest): Stream<SubscribeToItemsResponse> {
|
|
99
|
+
todo();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
subscribeToFeeds(request: SubscribeToFeedsRequest): Stream<SubscribeToFeedsResponse> {
|
|
103
|
+
return subscribeToFeeds({ feedStore: this.params.context.feedStore }, request);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
subscribeToFeedBlocks(request: SubscribeToFeedBlocksRequest): Stream<SubscribeToFeedBlocksResponse> {
|
|
107
|
+
return subscribeToFeedBlocks({ feedStore: this.params.context.feedStore }, request);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
getPartySnapshot(request: GetPartySnapshotRequest): Promise<GetPartySnapshotResponse> {
|
|
111
|
+
todo();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
savePartySnapshot(request: SavePartySnapshotRequest): Promise<SavePartySnapshotResponse> {
|
|
115
|
+
todo();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
clearSnapshots(request: ClearSnapshotsRequest): Promise<void> {
|
|
119
|
+
todo();
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
getNetworkPeers(request: GetNetworkPeersRequest): Promise<GetNetworkPeersResponse> {
|
|
123
|
+
todo();
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
subscribeToNetworkTopics(request: void): Stream<SubscribeToNetworkTopicsResponse> {
|
|
127
|
+
todo();
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
subscribeToSignalStatus(request: void): Stream<SubscribeToSignalStatusResponse> {
|
|
131
|
+
return subscribeToNetworkStatus({ networkManager: this.params.context.networkManager });
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
subscribeToSignalTrace(): Stream<SubscribeToSignalTraceResponse> {
|
|
135
|
+
return subscribeToSignalTrace({ networkManager: this.params.context.networkManager });
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
subscribeToSwarmInfo(): Stream<SubscribeToSwarmInfoResponse> {
|
|
139
|
+
return subscribeToSwarmInfo({ networkManager: this.params.context.networkManager });
|
|
140
|
+
}
|
|
141
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2022 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import assert from 'node:assert';
|
|
6
|
+
|
|
7
|
+
import { EventSubscriptions } from '@dxos/async';
|
|
8
|
+
import { Stream } from '@dxos/codec-protobuf';
|
|
9
|
+
import { ObjectModel } from '@dxos/object-model';
|
|
10
|
+
import {
|
|
11
|
+
AddKeyRecordRequest,
|
|
12
|
+
Contacts,
|
|
13
|
+
HaloService as HaloServiceRpc,
|
|
14
|
+
SignRequest,
|
|
15
|
+
SignResponse,
|
|
16
|
+
SetPreferenceRequest,
|
|
17
|
+
GetPreferenceRequest,
|
|
18
|
+
GetPreferenceResponse
|
|
19
|
+
} from '@dxos/protocols/proto/dxos/client';
|
|
20
|
+
|
|
21
|
+
import { HaloSigner } from '../signer';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* HALO service implementation.
|
|
25
|
+
*/
|
|
26
|
+
export class HaloService implements HaloServiceRpc {
|
|
27
|
+
constructor(
|
|
28
|
+
private readonly echo: any, // TODO(burdon): Remove.
|
|
29
|
+
private readonly signer?: HaloSigner
|
|
30
|
+
) {}
|
|
31
|
+
|
|
32
|
+
// TODO(burdon): Rename signMessage? (in interface).
|
|
33
|
+
// TODO(burdon): Why is this part of the interface? (Can it be factored out completely?)
|
|
34
|
+
async sign(request: SignRequest): Promise<SignResponse> {
|
|
35
|
+
assert(this.signer, 'Signer not set.');
|
|
36
|
+
assert(request.publicKey, 'Provide a public_key of the key that should be used for signing.');
|
|
37
|
+
const key = await this.echo.halo.keyring.getFullKey(request.publicKey);
|
|
38
|
+
assert(key, `Key not found: ${request.publicKey.toHex()}`);
|
|
39
|
+
return this.signer.sign(request, key);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async addKeyRecord(request: AddKeyRecordRequest): Promise<void> {
|
|
43
|
+
assert(request.keyRecord && request.keyRecord.publicKey, 'Missing key record.');
|
|
44
|
+
await this.echo.halo.keyring.addKeyRecord(request.keyRecord);
|
|
45
|
+
assert(await this.echo.halo.keyring.getKey(request.keyRecord.publicKey), 'Key not inserted correctly.');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// TODO(burdon): subscribeToContacts or just query/contacts with subscription object.
|
|
49
|
+
// ResultSet vs Stream?
|
|
50
|
+
subscribeContacts(): Stream<Contacts> {
|
|
51
|
+
return new Stream(({ next }) => {
|
|
52
|
+
next({ contacts: [] });
|
|
53
|
+
});
|
|
54
|
+
if (this.echo.halo.identity) {
|
|
55
|
+
// return resultSetToStream(this.echo.halo.queryContacts(), (contacts): Contacts => ({ contacts }));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// TODO(burdon): Explain non-initialized path.
|
|
59
|
+
return new Stream(({ next }) => {
|
|
60
|
+
// If profile does not exist, send an empty array.
|
|
61
|
+
if (!this.echo.halo.identity) {
|
|
62
|
+
next({ contacts: [] });
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const subscriptions = new EventSubscriptions();
|
|
66
|
+
setTimeout(async () => {
|
|
67
|
+
await this.echo.halo.identityReady.waitForCondition(() => !!this.echo.halo.identity);
|
|
68
|
+
|
|
69
|
+
const resultSet = this.echo.halo.queryContacts();
|
|
70
|
+
next({ contacts: resultSet.value });
|
|
71
|
+
subscriptions.add(resultSet.update.on(() => next({ contacts: resultSet.value })));
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
return () => subscriptions.clear();
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async setGlobalPreference(request: SetPreferenceRequest): Promise<void> {
|
|
79
|
+
assert(request.key, 'Missing key of property.');
|
|
80
|
+
const preferences: ObjectModel | undefined = this.echo.halo.identity?.preferences?.getGlobalPreferences()?.model;
|
|
81
|
+
assert(preferences, 'Preferences failed to load.');
|
|
82
|
+
await preferences.setProperty(request.key, request.value);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async getGlobalPreference(request: GetPreferenceRequest): Promise<GetPreferenceResponse> {
|
|
86
|
+
assert(request.key, 'Missing key of property.');
|
|
87
|
+
const preferences: ObjectModel | undefined = this.echo.halo.identity?.preferences?.getGlobalPreferences()?.model;
|
|
88
|
+
return {
|
|
89
|
+
value: preferences?.getProperty(request.key)
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async setDevicePreference(request: SetPreferenceRequest): Promise<void> {
|
|
94
|
+
assert(request.key, 'Missing key of property.');
|
|
95
|
+
const preferences: ObjectModel | undefined = this.echo.halo.identity?.preferences?.getDevicePreferences()?.model;
|
|
96
|
+
assert(preferences, 'Preferences failed to load.');
|
|
97
|
+
await preferences.setProperty(request.key, request.value);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async getDevicePreference(request: GetPreferenceRequest): Promise<GetPreferenceResponse> {
|
|
101
|
+
assert(request.key, 'Missing key of property.');
|
|
102
|
+
const preferences: ObjectModel | undefined = this.echo.halo.identity?.preferences?.getDevicePreferences()?.model;
|
|
103
|
+
return {
|
|
104
|
+
value: preferences?.getProperty(request.key)
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2022 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import assert from 'node:assert';
|
|
6
|
+
import { v4 } from 'uuid';
|
|
7
|
+
|
|
8
|
+
import { latch } from '@dxos/async';
|
|
9
|
+
import { Stream } from '@dxos/codec-protobuf';
|
|
10
|
+
import { todo } from '@dxos/debug';
|
|
11
|
+
import {
|
|
12
|
+
AuthenticateInvitationRequest,
|
|
13
|
+
CreateInvitationRequest,
|
|
14
|
+
CreateSnapshotRequest,
|
|
15
|
+
GetPartyDetailsRequest,
|
|
16
|
+
InvitationRequest,
|
|
17
|
+
InvitationState,
|
|
18
|
+
Party,
|
|
19
|
+
PartyDetails,
|
|
20
|
+
PartyService as PartyServiceRpc,
|
|
21
|
+
RedeemedInvitation,
|
|
22
|
+
SetPartyStateRequest,
|
|
23
|
+
SubscribeMembersRequest,
|
|
24
|
+
SubscribeMembersResponse,
|
|
25
|
+
SubscribePartiesResponse,
|
|
26
|
+
SubscribePartyRequest,
|
|
27
|
+
SubscribePartyResponse
|
|
28
|
+
} from '@dxos/protocols/proto/dxos/client';
|
|
29
|
+
import { PartySnapshot } from '@dxos/protocols/proto/dxos/echo/snapshot';
|
|
30
|
+
import { InvitationDescriptor } from '@dxos/protocols/proto/dxos/halo/invitations';
|
|
31
|
+
|
|
32
|
+
import { InvitationWrapper, InviteeInvitation, InviteeInvitations } from '../../invitations';
|
|
33
|
+
import { ServiceContext } from '../service-context';
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Party service implementation.
|
|
37
|
+
*/
|
|
38
|
+
// TODO(burdon): Rename Space.
|
|
39
|
+
export class PartyService implements PartyServiceRpc {
|
|
40
|
+
private inviteeInvitations: InviteeInvitations = new Map();
|
|
41
|
+
|
|
42
|
+
constructor(private readonly serviceContext: ServiceContext) {}
|
|
43
|
+
|
|
44
|
+
subscribeToParty(request: SubscribePartyRequest): Stream<SubscribePartyResponse> {
|
|
45
|
+
return new Stream(({ next }) => {
|
|
46
|
+
next({
|
|
47
|
+
party: {
|
|
48
|
+
publicKey: request.partyKey,
|
|
49
|
+
isOpen: true,
|
|
50
|
+
isActive: true,
|
|
51
|
+
members: []
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
// const update = (next: (message: SubscribePartyResponse) => void) => {
|
|
56
|
+
// try {
|
|
57
|
+
// const party = this.echo.getParty(request.party_key);
|
|
58
|
+
// next({
|
|
59
|
+
// party: party && {
|
|
60
|
+
// public_key: party.key,
|
|
61
|
+
// is_open: party.is_open,
|
|
62
|
+
// is_active: party.is_active,
|
|
63
|
+
// members: party.queryMembers().value
|
|
64
|
+
// }
|
|
65
|
+
// });
|
|
66
|
+
// } catch (err) {
|
|
67
|
+
// if (err instanceof InvalidStateError) {
|
|
68
|
+
// // Do nothing.
|
|
69
|
+
// } else {
|
|
70
|
+
// throw err;
|
|
71
|
+
// }
|
|
72
|
+
// }
|
|
73
|
+
// };
|
|
74
|
+
|
|
75
|
+
// const party = this.serviceContext.brane.getParty(request.party_key);
|
|
76
|
+
// if (party) {
|
|
77
|
+
// return new Stream(({ next }) => party.update.on(() => update(next)));
|
|
78
|
+
// } else {
|
|
79
|
+
// return new Stream(({ next }) => {
|
|
80
|
+
// let unsubscribeParty: () => void;
|
|
81
|
+
// const unsubscribeParties = this.echo.queryParties().subscribe((parties) => {
|
|
82
|
+
// const party = parties.find((party) => party.key.equals(request.party_key));
|
|
83
|
+
// if (party && !unsubscribeParty) {
|
|
84
|
+
// unsubscribeParty = party.update.on(() => update(next));
|
|
85
|
+
// }
|
|
86
|
+
// });
|
|
87
|
+
|
|
88
|
+
// update(next);
|
|
89
|
+
|
|
90
|
+
// return () => {
|
|
91
|
+
// unsubscribeParties();
|
|
92
|
+
// unsubscribeParty?.();
|
|
93
|
+
// };
|
|
94
|
+
// });
|
|
95
|
+
// }
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
subscribeParties() {
|
|
99
|
+
return new Stream<SubscribePartiesResponse>(({ next }) => {
|
|
100
|
+
const update = () => {
|
|
101
|
+
next({
|
|
102
|
+
parties: Array.from(this.serviceContext.spaceManager!.spaces.values()).map((space) => ({
|
|
103
|
+
publicKey: space.key,
|
|
104
|
+
isOpen: true,
|
|
105
|
+
isActive: true
|
|
106
|
+
}))
|
|
107
|
+
});
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
setTimeout(async () => {
|
|
111
|
+
if (!this.serviceContext.spaceManager) {
|
|
112
|
+
next({ parties: [] });
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
await this.serviceContext.initialized.wait();
|
|
116
|
+
|
|
117
|
+
update();
|
|
118
|
+
return this.serviceContext.spaceManager!.update.on(update);
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
async getPartyDetails(request: GetPartyDetailsRequest): Promise<PartyDetails> {
|
|
124
|
+
return todo();
|
|
125
|
+
// const party = this.echo.getParty(request.party_key) ?? raise(new SpaceNotFoundError(request.party_key));
|
|
126
|
+
// return {
|
|
127
|
+
// processedTimeframe: party.timeframe
|
|
128
|
+
// };
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async createParty(): Promise<Party> {
|
|
132
|
+
await this.serviceContext.initialized.wait();
|
|
133
|
+
const space = await this.serviceContext.spaceManager!.createSpace();
|
|
134
|
+
return {
|
|
135
|
+
publicKey: space.key,
|
|
136
|
+
isOpen: true,
|
|
137
|
+
isActive: true
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
async cloneParty(snapshot: PartySnapshot): Promise<Party> {
|
|
142
|
+
return todo();
|
|
143
|
+
// const party = await this.echo.cloneParty(snapshot);
|
|
144
|
+
// return {
|
|
145
|
+
// public_key: party.key,
|
|
146
|
+
// is_open: party.is_open,
|
|
147
|
+
// is_active: party.is_active
|
|
148
|
+
// };
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
async setPartyState(request: SetPartyStateRequest) {
|
|
152
|
+
return todo();
|
|
153
|
+
// const party = this.echo.getParty(request.party_key);
|
|
154
|
+
// if (!party) {
|
|
155
|
+
// throw new Error('Party not found');
|
|
156
|
+
// }
|
|
157
|
+
|
|
158
|
+
// if (request.open === true) {
|
|
159
|
+
// await party.open();
|
|
160
|
+
// } else if (request.open === false) {
|
|
161
|
+
// await party.close();
|
|
162
|
+
// } // Undefined preserves previous state.
|
|
163
|
+
|
|
164
|
+
// if (request.active_global === true) {
|
|
165
|
+
// await party.activate({ global: true });
|
|
166
|
+
// } else if (request.active_global === false) {
|
|
167
|
+
// await party.deactivate({ global: true });
|
|
168
|
+
// } // Undefined preserves previous state.
|
|
169
|
+
|
|
170
|
+
// if (request.active_device === true) {
|
|
171
|
+
// await party.activate({ device: true });
|
|
172
|
+
// } else if (request.active_device === false) {
|
|
173
|
+
// await party.deactivate({ device: true });
|
|
174
|
+
// } // Undefined preserves previous state.
|
|
175
|
+
// return {
|
|
176
|
+
// public_key: party.key,
|
|
177
|
+
// is_open: party.is_open,
|
|
178
|
+
// is_active: party.is_active
|
|
179
|
+
// };
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
createInvitation(request: CreateInvitationRequest): Stream<InvitationRequest> {
|
|
183
|
+
return new Stream(({ next, close }) => {
|
|
184
|
+
setTimeout(async () => {
|
|
185
|
+
try {
|
|
186
|
+
let invitation: InvitationWrapper;
|
|
187
|
+
if (!request.inviteeKey) {
|
|
188
|
+
// const secret = Buffer.from(generatePasscode());
|
|
189
|
+
// const secretProvider = async () => {
|
|
190
|
+
// next({ state: InvitationState.CONNECTED });
|
|
191
|
+
// return Buffer.from(secret);
|
|
192
|
+
// };
|
|
193
|
+
invitation = await this.serviceContext.createInvitation(request.partyKey, () => {
|
|
194
|
+
next({ state: InvitationState.SUCCESS });
|
|
195
|
+
close();
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
assert(invitation.type === InvitationDescriptor.Type.INTERACTIVE);
|
|
199
|
+
// invitation.secret = Buffer.from(secret);
|
|
200
|
+
} else {
|
|
201
|
+
todo();
|
|
202
|
+
// invitation = await party.invitationManager.createOfflineInvitation(request.invitee_key);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// TODO(burdon): Change stream type.
|
|
206
|
+
next({
|
|
207
|
+
state: InvitationState.WAITING_FOR_CONNECTION,
|
|
208
|
+
descriptor: invitation!.toProto()
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
// if (invitation.type === InvitationDescriptor.Type.OFFLINE) {
|
|
212
|
+
// close();
|
|
213
|
+
// }
|
|
214
|
+
} catch (err: any) {
|
|
215
|
+
next({ state: InvitationState.ERROR, error: err.message });
|
|
216
|
+
close();
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
acceptInvitation(request: InvitationDescriptor): Stream<RedeemedInvitation> {
|
|
223
|
+
return new Stream(({ next, close }) => {
|
|
224
|
+
const id = v4();
|
|
225
|
+
const [, secretTrigger] = latch();
|
|
226
|
+
const inviteeInvitation: InviteeInvitation = { secretTrigger };
|
|
227
|
+
|
|
228
|
+
// Secret will be provided separately (in AuthenticateInvitation).
|
|
229
|
+
// Process will continue when `secretLatch` resolves, triggered by `secretTrigger`.
|
|
230
|
+
// const secretProvider: SecretProvider = async () => {
|
|
231
|
+
// await secretLatch;
|
|
232
|
+
// const secret = inviteeInvitation.secret;
|
|
233
|
+
// if (!secret) {
|
|
234
|
+
// throw new Error('Secret not provided.');
|
|
235
|
+
// }
|
|
236
|
+
|
|
237
|
+
// return Buffer.from(secret);
|
|
238
|
+
// };
|
|
239
|
+
|
|
240
|
+
// Joining process is kicked off, and will await authentication with a secret.
|
|
241
|
+
const partyPromise = this.serviceContext.acceptInvitation(InvitationWrapper.fromProto(request));
|
|
242
|
+
this.inviteeInvitations.set(id, inviteeInvitation);
|
|
243
|
+
next({ id, state: InvitationState.CONNECTED });
|
|
244
|
+
|
|
245
|
+
partyPromise
|
|
246
|
+
.then((party) => {
|
|
247
|
+
next({ id, state: InvitationState.SUCCESS, partyKey: party.key });
|
|
248
|
+
})
|
|
249
|
+
.catch((err) => {
|
|
250
|
+
console.error(err);
|
|
251
|
+
next({ id, state: InvitationState.ERROR, error: String(err) });
|
|
252
|
+
})
|
|
253
|
+
.finally(() => {
|
|
254
|
+
close();
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
async authenticateInvitation(request: AuthenticateInvitationRequest) {
|
|
260
|
+
assert(request.processId, 'Process ID is missing.');
|
|
261
|
+
const invitation = this.inviteeInvitations.get(request.processId);
|
|
262
|
+
assert(invitation, 'Invitation not found.');
|
|
263
|
+
assert(request.secret, 'Secret not provided.');
|
|
264
|
+
|
|
265
|
+
// Supply the secret, and move the internal invitation process by triggering the secretTrigger.
|
|
266
|
+
invitation.secret = request.secret;
|
|
267
|
+
invitation.secretTrigger?.();
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
subscribeMembers(request: SubscribeMembersRequest): Stream<SubscribeMembersResponse> {
|
|
271
|
+
return new Stream(({ next }) => {
|
|
272
|
+
next({
|
|
273
|
+
members: []
|
|
274
|
+
});
|
|
275
|
+
});
|
|
276
|
+
// const party = this.echo.getParty(request.party_key);
|
|
277
|
+
// if (party) {
|
|
278
|
+
// return resultSetToStream(party.queryMembers(), (members): SubscribeMembersResponse => ({ members }));
|
|
279
|
+
// } else {
|
|
280
|
+
// return new Stream(({ next }) => {
|
|
281
|
+
// let unsubscribeMembers: () => void;
|
|
282
|
+
// const unsubscribeParties = this.echo.queryParties().subscribe((parties) => {
|
|
283
|
+
// const party = parties.find((party) => party.key.equals(request.party_key));
|
|
284
|
+
// if (!unsubscribeMembers && party) {
|
|
285
|
+
// const resultSet = party.queryMembers();
|
|
286
|
+
// next({ members: resultSet.value });
|
|
287
|
+
// unsubscribeMembers = resultSet.update.on(() => next({ members: resultSet.value }));
|
|
288
|
+
// }
|
|
289
|
+
// });
|
|
290
|
+
|
|
291
|
+
// return () => {
|
|
292
|
+
// unsubscribeParties();
|
|
293
|
+
// unsubscribeMembers();
|
|
294
|
+
// };
|
|
295
|
+
// });
|
|
296
|
+
// }
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
async createSnapshot(request: CreateSnapshotRequest): Promise<PartySnapshot> {
|
|
300
|
+
return todo();
|
|
301
|
+
// assert(request.party_key);
|
|
302
|
+
// const party = this.echo.getParty(request.party_key) ?? raise(new SpaceNotFoundError(request.party_key));
|
|
303
|
+
// return party.createSnapshot();
|
|
304
|
+
}
|
|
305
|
+
}
|