@dxos/client-services 0.8.4-main.5ea62a8 → 0.8.4-main.66e292d
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-JBVOLD57.mjs → chunk-PWKWJATU.mjs} +899 -1209
- package/dist/lib/browser/chunk-PWKWJATU.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +110 -135
- package/dist/lib/browser/index.mjs.map +2 -2
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +37 -66
- package/dist/lib/browser/testing/index.mjs.map +2 -2
- package/dist/lib/node-esm/{chunk-AADRC6MD.mjs → chunk-7NQQ5F2Q.mjs} +900 -1210
- package/dist/lib/node-esm/chunk-7NQQ5F2Q.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +110 -135
- package/dist/lib/node-esm/index.mjs.map +2 -2
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/testing/index.mjs +37 -66
- package/dist/lib/node-esm/testing/index.mjs.map +2 -2
- package/dist/types/src/packlets/agents/edge-agent-service.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts +2 -2
- package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitation-guest-extenstion.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitation-host-extension.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitation-protocol.d.ts +2 -3
- package/dist/types/src/packlets/invitations/invitation-protocol.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts +2 -2
- package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts.map +1 -1
- package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
- package/dist/types/src/packlets/space-export/space-archive-writer.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/spaces-service.d.ts.map +1 -1
- package/dist/types/src/version.d.ts +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +39 -39
- package/src/packlets/agents/edge-agent-service.ts +11 -1
- package/src/packlets/devices/devices-service.ts +1 -1
- package/src/packlets/identity/identity.test.ts +4 -4
- package/src/packlets/invitations/device-invitation-protocol.ts +3 -3
- package/src/packlets/invitations/invitation-guest-extenstion.ts +6 -4
- package/src/packlets/invitations/invitation-host-extension.ts +6 -4
- package/src/packlets/invitations/invitation-protocol.ts +2 -3
- package/src/packlets/invitations/invitations-handler.ts +1 -1
- package/src/packlets/invitations/space-invitation-protocol.ts +7 -13
- package/src/packlets/logging/logging-service.ts +1 -1
- package/src/packlets/services/service-host.ts +6 -0
- package/src/packlets/space-export/space-archive-reader.ts +2 -2
- package/src/packlets/space-export/space-archive-writer.ts +4 -3
- package/src/packlets/spaces/data-space-manager.ts +28 -8
- package/src/packlets/spaces/data-space.ts +1 -1
- package/src/packlets/spaces/edge-feed-replicator.test.ts +1 -1
- package/src/packlets/spaces/edge-feed-replicator.ts +1 -1
- package/src/packlets/spaces/notarization-plugin.ts +2 -2
- package/src/packlets/spaces/spaces-service.ts +11 -8
- package/src/packlets/storage/storage.ts +4 -4
- package/src/version.ts +1 -1
- package/dist/lib/browser/chunk-JBVOLD57.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-AADRC6MD.mjs.map +0 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/client-services",
|
|
3
|
-
"version": "0.8.4-main.
|
|
3
|
+
"version": "0.8.4-main.66e292d",
|
|
4
4
|
"description": "DXOS client services implementation",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -43,52 +43,52 @@
|
|
|
43
43
|
"src"
|
|
44
44
|
],
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@automerge/automerge": "3.1.
|
|
47
|
-
"@automerge/automerge-repo": "2.
|
|
46
|
+
"@automerge/automerge": "3.1.2",
|
|
47
|
+
"@automerge/automerge-repo": "2.4.0",
|
|
48
48
|
"@obsidize/tar-browserify": "^5.2.0",
|
|
49
49
|
"cbor-x": "^1.5.4",
|
|
50
50
|
"platform": "^1.3.6",
|
|
51
|
-
"@dxos/async": "0.8.4-main.
|
|
52
|
-
"@dxos/codec-protobuf": "0.8.4-main.
|
|
53
|
-
"@dxos/client-protocol": "0.8.4-main.
|
|
54
|
-
"@dxos/
|
|
55
|
-
"@dxos/credentials": "0.8.4-main.
|
|
56
|
-
"@dxos/debug": "0.8.4-main.
|
|
57
|
-
"@dxos/crypto": "0.8.4-main.
|
|
58
|
-
"@dxos/
|
|
59
|
-
"@dxos/echo
|
|
60
|
-
"@dxos/echo-
|
|
61
|
-
"@dxos/
|
|
62
|
-
"@dxos/
|
|
63
|
-
"@dxos/
|
|
64
|
-
"@dxos/
|
|
65
|
-
"@dxos/
|
|
66
|
-
"@dxos/
|
|
67
|
-
"@dxos/
|
|
68
|
-
"@dxos/
|
|
69
|
-
"@dxos/
|
|
70
|
-
"@dxos/
|
|
71
|
-
"@dxos/
|
|
72
|
-
"@dxos/network-manager": "0.8.4-main.
|
|
73
|
-
"@dxos/node-std": "0.8.4-main.
|
|
74
|
-
"@dxos/protocols": "0.8.4-main.
|
|
75
|
-
"@dxos/random-access-storage": "0.8.4-main.
|
|
76
|
-
"@dxos/
|
|
77
|
-
"@dxos/
|
|
78
|
-
"@dxos/
|
|
79
|
-
"@dxos/teleport-extension-
|
|
80
|
-
"@dxos/
|
|
81
|
-
"@dxos/
|
|
82
|
-
"@dxos/
|
|
83
|
-
"@dxos/websocket-rpc": "0.8.4-main.
|
|
84
|
-
"@dxos/
|
|
51
|
+
"@dxos/async": "0.8.4-main.66e292d",
|
|
52
|
+
"@dxos/codec-protobuf": "0.8.4-main.66e292d",
|
|
53
|
+
"@dxos/client-protocol": "0.8.4-main.66e292d",
|
|
54
|
+
"@dxos/config": "0.8.4-main.66e292d",
|
|
55
|
+
"@dxos/credentials": "0.8.4-main.66e292d",
|
|
56
|
+
"@dxos/debug": "0.8.4-main.66e292d",
|
|
57
|
+
"@dxos/crypto": "0.8.4-main.66e292d",
|
|
58
|
+
"@dxos/context": "0.8.4-main.66e292d",
|
|
59
|
+
"@dxos/echo": "0.8.4-main.66e292d",
|
|
60
|
+
"@dxos/echo-db": "0.8.4-main.66e292d",
|
|
61
|
+
"@dxos/echo-protocol": "0.8.4-main.66e292d",
|
|
62
|
+
"@dxos/feed-store": "0.8.4-main.66e292d",
|
|
63
|
+
"@dxos/echo-pipeline": "0.8.4-main.66e292d",
|
|
64
|
+
"@dxos/keyring": "0.8.4-main.66e292d",
|
|
65
|
+
"@dxos/edge-client": "0.8.4-main.66e292d",
|
|
66
|
+
"@dxos/indexing": "0.8.4-main.66e292d",
|
|
67
|
+
"@dxos/keys": "0.8.4-main.66e292d",
|
|
68
|
+
"@dxos/invariant": "0.8.4-main.66e292d",
|
|
69
|
+
"@dxos/kv-store": "0.8.4-main.66e292d",
|
|
70
|
+
"@dxos/lock-file": "0.8.4-main.66e292d",
|
|
71
|
+
"@dxos/log": "0.8.4-main.66e292d",
|
|
72
|
+
"@dxos/network-manager": "0.8.4-main.66e292d",
|
|
73
|
+
"@dxos/node-std": "0.8.4-main.66e292d",
|
|
74
|
+
"@dxos/protocols": "0.8.4-main.66e292d",
|
|
75
|
+
"@dxos/random-access-storage": "0.8.4-main.66e292d",
|
|
76
|
+
"@dxos/messaging": "0.8.4-main.66e292d",
|
|
77
|
+
"@dxos/rpc": "0.8.4-main.66e292d",
|
|
78
|
+
"@dxos/teleport": "0.8.4-main.66e292d",
|
|
79
|
+
"@dxos/teleport-extension-gossip": "0.8.4-main.66e292d",
|
|
80
|
+
"@dxos/tracing": "0.8.4-main.66e292d",
|
|
81
|
+
"@dxos/util": "0.8.4-main.66e292d",
|
|
82
|
+
"@dxos/timeframe": "0.8.4-main.66e292d",
|
|
83
|
+
"@dxos/websocket-rpc": "0.8.4-main.66e292d",
|
|
84
|
+
"@dxos/teleport-extension-object-sync": "0.8.4-main.66e292d"
|
|
85
85
|
},
|
|
86
86
|
"devDependencies": {
|
|
87
87
|
"@types/platform": "^1.3.4",
|
|
88
88
|
"@types/readable-stream": "^2.3.9",
|
|
89
89
|
"get-port-please": "^3.1.1",
|
|
90
|
-
"@dxos/
|
|
91
|
-
"@dxos/
|
|
90
|
+
"@dxos/test-utils": "0.8.4-main.66e292d",
|
|
91
|
+
"@dxos/signal": "0.8.4-main.66e292d"
|
|
92
92
|
},
|
|
93
93
|
"publishConfig": {
|
|
94
94
|
"access": "public"
|
|
@@ -25,7 +25,17 @@ export class EdgeAgentServiceImpl implements EdgeAgentService {
|
|
|
25
25
|
queryEdgeStatus(): Stream<QueryEdgeStatusResponse> {
|
|
26
26
|
return new Stream(({ ctx, next }) => {
|
|
27
27
|
const update = () => {
|
|
28
|
-
next({
|
|
28
|
+
next({
|
|
29
|
+
status: this._edgeConnection?.status ?? {
|
|
30
|
+
state: EdgeStatus.ConnectionState.NOT_CONNECTED,
|
|
31
|
+
rtt: 0,
|
|
32
|
+
uptime: 0,
|
|
33
|
+
rateBytesUp: 0,
|
|
34
|
+
rateBytesDown: 0,
|
|
35
|
+
messagesSent: 0,
|
|
36
|
+
messagesReceived: 0,
|
|
37
|
+
},
|
|
38
|
+
});
|
|
29
39
|
};
|
|
30
40
|
|
|
31
41
|
this._edgeConnection?.statusChanged.on(ctx, update);
|
|
@@ -44,7 +44,7 @@ export class DevicesServiceImpl implements DevicesService {
|
|
|
44
44
|
presence = Device.PresenceState.ONLINE;
|
|
45
45
|
} else if (profile.os?.toUpperCase() === 'EDGE') {
|
|
46
46
|
presence =
|
|
47
|
-
this._edgeConnection?.status === EdgeStatus.CONNECTED
|
|
47
|
+
this._edgeConnection?.status.state === EdgeStatus.ConnectionState.CONNECTED
|
|
48
48
|
? Device.PresenceState.ONLINE
|
|
49
49
|
: Device.PresenceState.OFFLINE;
|
|
50
50
|
} else {
|
|
@@ -109,16 +109,16 @@ describe('identity/identity', () => {
|
|
|
109
109
|
|
|
110
110
|
test('edge feed replicator', async () => {
|
|
111
111
|
let replicationStarted = false;
|
|
112
|
-
let status = EdgeStatus.NOT_CONNECTED;
|
|
112
|
+
let status = EdgeStatus.ConnectionState.NOT_CONNECTED;
|
|
113
113
|
const listeners: Array<() => void> = [];
|
|
114
114
|
const setup = await setupIdentity({
|
|
115
115
|
edgeConnection: {
|
|
116
116
|
statusChanged: new Event(),
|
|
117
117
|
get status() {
|
|
118
|
-
return status;
|
|
118
|
+
return { state: status };
|
|
119
119
|
},
|
|
120
120
|
onReconnected: (listener) => {
|
|
121
|
-
if (status === EdgeStatus.CONNECTED) {
|
|
121
|
+
if (status === EdgeStatus.ConnectionState.CONNECTED) {
|
|
122
122
|
listener();
|
|
123
123
|
} else {
|
|
124
124
|
listeners.push(listener);
|
|
@@ -138,7 +138,7 @@ describe('identity/identity', () => {
|
|
|
138
138
|
|
|
139
139
|
await writeGenesisCredential(setup);
|
|
140
140
|
listeners.forEach((callback) => callback());
|
|
141
|
-
status = EdgeStatus.CONNECTED;
|
|
141
|
+
status = EdgeStatus.ConnectionState.CONNECTED;
|
|
142
142
|
|
|
143
143
|
await expect.poll(() => replicationStarted).toBeTruthy();
|
|
144
144
|
});
|
|
@@ -6,7 +6,7 @@ import { getCredentialAssertion } from '@dxos/credentials';
|
|
|
6
6
|
import { invariant } from '@dxos/invariant';
|
|
7
7
|
import { type Keyring } from '@dxos/keyring';
|
|
8
8
|
import { type PublicKey } from '@dxos/keys';
|
|
9
|
-
import { AlreadyJoinedError
|
|
9
|
+
import { AlreadyJoinedError } from '@dxos/protocols';
|
|
10
10
|
import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
|
|
11
11
|
import type { DeviceProfileDocument } from '@dxos/protocols/proto/dxos/halo/credentials';
|
|
12
12
|
import {
|
|
@@ -32,7 +32,7 @@ export class DeviceInvitationProtocol implements InvitationProtocol {
|
|
|
32
32
|
};
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
checkCanInviteNewMembers():
|
|
35
|
+
checkCanInviteNewMembers(): Error | undefined {
|
|
36
36
|
return undefined;
|
|
37
37
|
}
|
|
38
38
|
|
|
@@ -71,7 +71,7 @@ export class DeviceInvitationProtocol implements InvitationProtocol {
|
|
|
71
71
|
try {
|
|
72
72
|
const identity = this._getIdentity();
|
|
73
73
|
if (identity) {
|
|
74
|
-
return new AlreadyJoinedError('Currently only one identity per client is supported.');
|
|
74
|
+
return new AlreadyJoinedError({ message: 'Currently only one identity per client is supported.' });
|
|
75
75
|
}
|
|
76
76
|
} catch {
|
|
77
77
|
// No identity.
|
|
@@ -97,10 +97,12 @@ export class InvitationGuestExtension
|
|
|
97
97
|
await cancelWithContext(this._ctx, this._remoteOptionsTrigger.wait({ timeout: OPTIONS_TIMEOUT }));
|
|
98
98
|
log.verbose('options received');
|
|
99
99
|
if (this._remoteOptions?.role !== InvitationOptions.Role.HOST) {
|
|
100
|
-
throw new InvalidInvitationExtensionRoleError(
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
100
|
+
throw new InvalidInvitationExtensionRoleError({
|
|
101
|
+
context: {
|
|
102
|
+
expected: InvitationOptions.Role.HOST,
|
|
103
|
+
remoteOptions: this._remoteOptions,
|
|
104
|
+
remotePeerId: context.remotePeerId,
|
|
105
|
+
},
|
|
104
106
|
});
|
|
105
107
|
}
|
|
106
108
|
|
|
@@ -245,10 +245,12 @@ export class InvitationHostExtension
|
|
|
245
245
|
await cancelWithContext(this._ctx, this._remoteOptionsTrigger.wait({ timeout: OPTIONS_TIMEOUT }));
|
|
246
246
|
log.verbose('options received');
|
|
247
247
|
if (this._remoteOptions?.role !== InvitationOptions.Role.GUEST) {
|
|
248
|
-
throw new InvalidInvitationExtensionRoleError(
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
248
|
+
throw new InvalidInvitationExtensionRoleError({
|
|
249
|
+
context: {
|
|
250
|
+
expected: InvitationOptions.Role.GUEST,
|
|
251
|
+
remoteOptions: this._remoteOptions,
|
|
252
|
+
remotePeerId: context.remotePeerId,
|
|
253
|
+
},
|
|
252
254
|
});
|
|
253
255
|
}
|
|
254
256
|
this._callbacks.onStateUpdate(Invitation.State.CONNECTED);
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { type PublicKey } from '@dxos/keys';
|
|
6
|
-
import type { ApiError } from '@dxos/protocols';
|
|
7
6
|
import type { Invitation } from '@dxos/protocols/proto/dxos/client/services';
|
|
8
7
|
import type { DeviceProfileDocument, ProfileDocument } from '@dxos/protocols/proto/dxos/halo/credentials';
|
|
9
8
|
import type {
|
|
@@ -26,7 +25,7 @@ export interface InvitationProtocol {
|
|
|
26
25
|
// Host
|
|
27
26
|
//
|
|
28
27
|
|
|
29
|
-
checkCanInviteNewMembers():
|
|
28
|
+
checkCanInviteNewMembers(): Error | undefined;
|
|
30
29
|
|
|
31
30
|
/**
|
|
32
31
|
* Protocol-specific information to include in the invitation.
|
|
@@ -58,7 +57,7 @@ export interface InvitationProtocol {
|
|
|
58
57
|
*
|
|
59
58
|
* For example, the guest may already be a member of the space.
|
|
60
59
|
*/
|
|
61
|
-
checkInvitation(invitation: Partial<Invitation>):
|
|
60
|
+
checkInvitation(invitation: Partial<Invitation>): Error | undefined;
|
|
62
61
|
|
|
63
62
|
/**
|
|
64
63
|
* Get profile information to send to the host to identify the guest.
|
|
@@ -503,7 +503,7 @@ export class InvitationsHandler {
|
|
|
503
503
|
const checkInvitation = (protocol: InvitationProtocol, invitation: Partial<Invitation>) => {
|
|
504
504
|
const expiresOn = getExpirationTime(invitation);
|
|
505
505
|
if (expiresOn && expiresOn.getTime() < Date.now()) {
|
|
506
|
-
return new InvalidInvitationError('Invitation already expired.');
|
|
506
|
+
return new InvalidInvitationError({ message: 'Invitation already expired.' });
|
|
507
507
|
}
|
|
508
508
|
return protocol.checkInvitation(invitation);
|
|
509
509
|
};
|
|
@@ -12,13 +12,7 @@ import { invariant } from '@dxos/invariant';
|
|
|
12
12
|
import { type Keyring } from '@dxos/keyring';
|
|
13
13
|
import { type PublicKey } from '@dxos/keys';
|
|
14
14
|
import { log } from '@dxos/log';
|
|
15
|
-
import {
|
|
16
|
-
AlreadyJoinedError,
|
|
17
|
-
type ApiError,
|
|
18
|
-
AuthorizationError,
|
|
19
|
-
InvalidInvitationError,
|
|
20
|
-
SpaceNotFoundError,
|
|
21
|
-
} from '@dxos/protocols';
|
|
15
|
+
import { AlreadyJoinedError, AuthorizationError, InvalidInvitationError, SpaceNotFoundError } from '@dxos/protocols';
|
|
22
16
|
import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
|
|
23
17
|
import { type ProfileDocument, SpaceMember } from '@dxos/protocols/proto/dxos/halo/credentials';
|
|
24
18
|
import {
|
|
@@ -48,16 +42,16 @@ export class SpaceInvitationProtocol implements InvitationProtocol {
|
|
|
48
42
|
};
|
|
49
43
|
}
|
|
50
44
|
|
|
51
|
-
checkCanInviteNewMembers():
|
|
45
|
+
checkCanInviteNewMembers(): Error | undefined {
|
|
52
46
|
if (this._spaceKey == null) {
|
|
53
|
-
return new InvalidInvitationError('No spaceKey was provided for a space invitation.');
|
|
47
|
+
return new InvalidInvitationError({ message: 'No spaceKey was provided for a space invitation.' });
|
|
54
48
|
}
|
|
55
49
|
const space = this._spaceManager.spaces.get(this._spaceKey);
|
|
56
50
|
if (space == null) {
|
|
57
51
|
return new SpaceNotFoundError(this._spaceKey);
|
|
58
52
|
}
|
|
59
53
|
if (!space?.inner.spaceState.hasMembershipManagementPermission(this._signingContext.identityKey)) {
|
|
60
|
-
return new AuthorizationError('No member management permission.');
|
|
54
|
+
return new AuthorizationError({ message: 'No member management permission.' });
|
|
61
55
|
}
|
|
62
56
|
return undefined;
|
|
63
57
|
}
|
|
@@ -148,10 +142,10 @@ export class SpaceInvitationProtocol implements InvitationProtocol {
|
|
|
148
142
|
|
|
149
143
|
checkInvitation(invitation: Partial<Invitation>): InvalidInvitationError | AlreadyJoinedError | undefined {
|
|
150
144
|
if (invitation.spaceKey == null) {
|
|
151
|
-
return new InvalidInvitationError('No spaceKey was provided for a space invitation.');
|
|
145
|
+
return new InvalidInvitationError({ message: 'No spaceKey was provided for a space invitation.' });
|
|
152
146
|
}
|
|
153
147
|
if (this._spaceManager.spaces.has(invitation.spaceKey)) {
|
|
154
|
-
return new AlreadyJoinedError('Already joined space.');
|
|
148
|
+
return new AlreadyJoinedError({ message: 'Already joined space.' });
|
|
155
149
|
}
|
|
156
150
|
}
|
|
157
151
|
|
|
@@ -184,7 +178,7 @@ export class SpaceInvitationProtocol implements InvitationProtocol {
|
|
|
184
178
|
invariant(credential.subject.id.equals(this._signingContext.identityKey));
|
|
185
179
|
|
|
186
180
|
if (this._spaceManager.spaces.has(assertion.spaceKey)) {
|
|
187
|
-
throw new AlreadyJoinedError('Already joined space.');
|
|
181
|
+
throw new AlreadyJoinedError({ message: 'Already joined space.' });
|
|
188
182
|
}
|
|
189
183
|
|
|
190
184
|
// Create local space.
|
|
@@ -37,7 +37,7 @@ export class LoggingServiceImpl implements LoggingService {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
async close(): Promise<void> {
|
|
40
|
-
const index = log.runtimeConfig.processors.findIndex((processor) => processor === this._logProcessor);
|
|
40
|
+
const index = log.runtimeConfig.processors.findIndex((processor: LogProcessor) => processor === this._logProcessor);
|
|
41
41
|
log.runtimeConfig.processors.splice(index, 1);
|
|
42
42
|
}
|
|
43
43
|
|
|
@@ -408,6 +408,12 @@ export class ClientServicesHost {
|
|
|
408
408
|
this._resetting = true;
|
|
409
409
|
this._statusUpdate.emit();
|
|
410
410
|
await this._serviceContext?.close();
|
|
411
|
+
// Clear LevelDB contents to remove all persisted Echo/Automerge/index data.
|
|
412
|
+
try {
|
|
413
|
+
await this._level!.clear();
|
|
414
|
+
} catch (err) {
|
|
415
|
+
log.warn('failed to clear leveldb during reset', { err });
|
|
416
|
+
}
|
|
411
417
|
await this._storage!.reset();
|
|
412
418
|
log.info('reset');
|
|
413
419
|
log.trace('dxos.sdk.client-services-host.reset', trace.end({ id: traceId }));
|
|
@@ -18,7 +18,7 @@ export const extractSpaceArchive = async (archive: SpaceArchive): Promise<Extrac
|
|
|
18
18
|
const { Archive } = await import('@obsidize/tar-browserify');
|
|
19
19
|
const { entries } = await Archive.extract(archive.contents);
|
|
20
20
|
const metadataEntry = entries.find((entry) => entry.fileName === SpaceArchiveFileStructure.metadata);
|
|
21
|
-
assertArgument(metadataEntry, 'Metadata entry not found');
|
|
21
|
+
assertArgument(metadataEntry, 'metadataEntry', 'Metadata entry not found');
|
|
22
22
|
const metadata = JSON.parse(metadataEntry.getContentAsText());
|
|
23
23
|
const documents: Record<DocumentId, Uint8Array> = {};
|
|
24
24
|
for (const entry of entries.filter((entry) => entry.fileName.startsWith(`${SpaceArchiveFileStructure.documents}/`))) {
|
|
@@ -29,6 +29,6 @@ export const extractSpaceArchive = async (archive: SpaceArchive): Promise<Extrac
|
|
|
29
29
|
documents[documentId] = entry.content ?? failedInvariant();
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
log
|
|
32
|
+
log('extracted space archive', { metadata, documents });
|
|
33
33
|
return { metadata, documents };
|
|
34
34
|
};
|
|
@@ -44,14 +44,14 @@ export class SpaceArchiveWriter extends Resource {
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
async setCurrentRootUrl(url: string): Promise<void> {
|
|
47
|
-
assertArgument(url.startsWith('automerge:'), 'Invalid root URL');
|
|
47
|
+
assertArgument(url.startsWith('automerge:'), 'url', 'Invalid root URL');
|
|
48
48
|
assertState(this._tar, 'Not open');
|
|
49
49
|
assertState(this._meta, 'Not started');
|
|
50
50
|
this._currentRootUrl = url;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
async writeDocument(documentId: string, data: Uint8Array): Promise<void> {
|
|
54
|
-
assertArgument(!documentId.startsWith('automerge:'), 'Invalid document ID');
|
|
54
|
+
assertArgument(!documentId.startsWith('automerge:'), 'documentId', 'Invalid document ID');
|
|
55
55
|
assertState(this._archive, 'Not open');
|
|
56
56
|
this._archive.addBinaryFile(`${SpaceArchiveFileStructure.documents}/${documentId}.bin`, data);
|
|
57
57
|
}
|
|
@@ -76,7 +76,8 @@ export class SpaceArchiveWriter extends Resource {
|
|
|
76
76
|
const binary = this._archive.toUint8Array();
|
|
77
77
|
|
|
78
78
|
return {
|
|
79
|
-
|
|
79
|
+
// TODO(wittjosiah): Factor out file name construction.
|
|
80
|
+
filename: `${new Date().toISOString()}-${this._meta.spaceId}.tar`,
|
|
80
81
|
contents: binary,
|
|
81
82
|
};
|
|
82
83
|
}
|
|
@@ -6,7 +6,7 @@ import { type Doc } from '@automerge/automerge';
|
|
|
6
6
|
import { type AutomergeUrl, type DocHandle, type DocumentId, interpretAsDocumentId } from '@automerge/automerge-repo';
|
|
7
7
|
|
|
8
8
|
import { Event, synchronized, trackLeaks } from '@dxos/async';
|
|
9
|
-
import {
|
|
9
|
+
import { SpaceProperties } from '@dxos/client-protocol';
|
|
10
10
|
import { Context, LifecycleState, Resource, cancelWithContext } from '@dxos/context';
|
|
11
11
|
import {
|
|
12
12
|
type CredentialSigner,
|
|
@@ -15,6 +15,8 @@ import {
|
|
|
15
15
|
createAdmissionCredentials,
|
|
16
16
|
getCredentialAssertion,
|
|
17
17
|
} from '@dxos/credentials';
|
|
18
|
+
import { Type } from '@dxos/echo';
|
|
19
|
+
import { getTypeReference } from '@dxos/echo/internal';
|
|
18
20
|
import {
|
|
19
21
|
AuthStatus,
|
|
20
22
|
CredentialServerExtension,
|
|
@@ -37,12 +39,11 @@ import {
|
|
|
37
39
|
createIdFromSpaceKey,
|
|
38
40
|
encodeReference,
|
|
39
41
|
} from '@dxos/echo-protocol';
|
|
40
|
-
import { ObjectId, getTypeReference } from '@dxos/echo-schema';
|
|
41
42
|
import type { EdgeConnection, EdgeHttpClient } from '@dxos/edge-client';
|
|
42
43
|
import { type FeedStore, writeMessages } from '@dxos/feed-store';
|
|
43
44
|
import { assertArgument, assertState, failedInvariant, invariant } from '@dxos/invariant';
|
|
44
45
|
import { type Keyring } from '@dxos/keyring';
|
|
45
|
-
import { PublicKey, type SpaceId } from '@dxos/keys';
|
|
46
|
+
import { ObjectId, PublicKey, type SpaceId } from '@dxos/keys';
|
|
46
47
|
import { log } from '@dxos/log';
|
|
47
48
|
import { AlreadyJoinedError, trace as Trace } from '@dxos/protocols';
|
|
48
49
|
import { Invitation, SpaceState } from '@dxos/protocols/proto/dxos/client/services';
|
|
@@ -184,7 +185,7 @@ export class DataSpaceManager extends Resource {
|
|
|
184
185
|
await rootHandle?.whenReady();
|
|
185
186
|
const rootDoc = rootHandle?.doc();
|
|
186
187
|
|
|
187
|
-
const properties = rootDoc && findInlineObjectOfType(rootDoc,
|
|
188
|
+
const properties = rootDoc && findInlineObjectOfType(rootDoc, Type.getTypename(SpaceProperties));
|
|
188
189
|
|
|
189
190
|
return {
|
|
190
191
|
key: space.key.toHex(),
|
|
@@ -245,7 +246,11 @@ export class DataSpaceManager extends Resource {
|
|
|
245
246
|
*/
|
|
246
247
|
@synchronized
|
|
247
248
|
async createSpace(options: CreateSpaceOptions = {}): Promise<DataSpace> {
|
|
248
|
-
assertArgument(
|
|
249
|
+
assertArgument(
|
|
250
|
+
!!options.rootUrl === !!options.documents,
|
|
251
|
+
'options',
|
|
252
|
+
'root url must be required when providing documents',
|
|
253
|
+
);
|
|
249
254
|
|
|
250
255
|
assertState(this._lifecycleState === LifecycleState.OPEN, 'Not open.');
|
|
251
256
|
const spaceKey = await this._keyring.createKey();
|
|
@@ -275,7 +280,18 @@ export class DataSpaceManager extends Resource {
|
|
|
275
280
|
await Promise.all(
|
|
276
281
|
Object.entries(options.documents).map(async ([documentId, data]) => {
|
|
277
282
|
log('creating document...', { documentId });
|
|
278
|
-
|
|
283
|
+
// TODO(dmaretskyi): Broken types -- the bytes get interpreted as CRDT data.
|
|
284
|
+
const newDoc = await this._echoHost.createDoc(data as any as DatabaseDirectory, {
|
|
285
|
+
preserveHistory: true,
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
// The archived documents might have the spaceKey from the space they were expored from, we need to update it to the new spaceKey.
|
|
289
|
+
if (newDoc.doc().access !== undefined && newDoc.doc().access!.spaceKey !== spaceKey.toHex()) {
|
|
290
|
+
newDoc.change((doc) => {
|
|
291
|
+
doc.access!.spaceKey = spaceKey.toHex();
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
|
|
279
295
|
documentIdMapping[documentId as DocumentId] = newDoc.documentId;
|
|
280
296
|
}),
|
|
281
297
|
);
|
|
@@ -293,6 +309,7 @@ export class DataSpaceManager extends Resource {
|
|
|
293
309
|
} else {
|
|
294
310
|
root = await this._echoHost.createSpaceRoot(spaceKey);
|
|
295
311
|
}
|
|
312
|
+
await this._echoHost.flush();
|
|
296
313
|
|
|
297
314
|
log('constructing space...', { spaceKey });
|
|
298
315
|
|
|
@@ -326,9 +343,12 @@ export class DataSpaceManager extends Resource {
|
|
|
326
343
|
log.warn('waiting for space root to be ready', { spaceId: space.id });
|
|
327
344
|
await space.databaseRoot.handle.whenReady();
|
|
328
345
|
}
|
|
329
|
-
|
|
346
|
+
|
|
347
|
+
const [_, properties] =
|
|
348
|
+
findInlineObjectOfType(space.databaseRoot.doc()!, Type.getTypename(SpaceProperties)) ?? [];
|
|
330
349
|
return properties?.data?.[DEFAULT_SPACE_KEY] === this._signingContext.identityKey.toHex();
|
|
331
350
|
}
|
|
351
|
+
|
|
332
352
|
case SpaceDocVersion.LEGACY: {
|
|
333
353
|
throw new Error('Legacy space version is not supported');
|
|
334
354
|
}
|
|
@@ -346,7 +366,7 @@ export class DataSpaceManager extends Resource {
|
|
|
346
366
|
// TODO(dmaretskyi): Better API for low-level data access.
|
|
347
367
|
const properties: ObjectStructure = {
|
|
348
368
|
system: {
|
|
349
|
-
type: encodeReference(getTypeReference(
|
|
369
|
+
type: encodeReference(getTypeReference(SpaceProperties)!),
|
|
350
370
|
},
|
|
351
371
|
data: {
|
|
352
372
|
[DEFAULT_SPACE_KEY]: this._signingContext.identityKey.toHex(),
|
|
@@ -331,7 +331,7 @@ export class DataSpace {
|
|
|
331
331
|
@trace.span({ showInBrowserTimeline: true })
|
|
332
332
|
async initializeDataPipeline(): Promise<void> {
|
|
333
333
|
if (this._state !== SpaceState.SPACE_CONTROL_ONLY) {
|
|
334
|
-
throw new SystemError('Invalid operation');
|
|
334
|
+
throw new SystemError({ message: 'Invalid operation' });
|
|
335
335
|
}
|
|
336
336
|
|
|
337
337
|
this._state = SpaceState.SPACE_INITIALIZING;
|
|
@@ -45,7 +45,7 @@ describe('EdgeFeedReplicator', () => {
|
|
|
45
45
|
const { endpoint, admitConnection, messageSink } = await createEdge();
|
|
46
46
|
const { messenger } = await createClient(endpoint);
|
|
47
47
|
admitConnection.wake();
|
|
48
|
-
await expect.poll(() => messenger.status).toBe(EdgeStatus.CONNECTED);
|
|
48
|
+
await expect.poll(() => messenger.status.state).toBe(EdgeStatus.ConnectionState.CONNECTED);
|
|
49
49
|
|
|
50
50
|
await attachReplicator(messenger);
|
|
51
51
|
await expect.poll(() => messageSink.length).toEqual(1);
|
|
@@ -87,7 +87,7 @@ export class EdgeFeedReplicator extends Resource {
|
|
|
87
87
|
|
|
88
88
|
private async _handleReconnect(): Promise<void> {
|
|
89
89
|
await this._resetConnection();
|
|
90
|
-
if (this._messenger.status === EdgeStatus.CONNECTED) {
|
|
90
|
+
if (this._messenger.status.state === EdgeStatus.ConnectionState.CONNECTED) {
|
|
91
91
|
this._startReplication();
|
|
92
92
|
}
|
|
93
93
|
}
|
|
@@ -392,10 +392,10 @@ export class NotarizationPlugin extends Resource implements CredentialProcessor
|
|
|
392
392
|
}
|
|
393
393
|
|
|
394
394
|
const handleEdgeError = (error: any) => {
|
|
395
|
-
if (!(error instanceof EdgeCallFailedError) || error.
|
|
395
|
+
if (!(error instanceof EdgeCallFailedError) || error.data) {
|
|
396
396
|
log.catch(error);
|
|
397
397
|
} else {
|
|
398
|
-
log.info('Edge notarization failure', {
|
|
398
|
+
log.info('Edge notarization failure', { message: error.message });
|
|
399
399
|
}
|
|
400
400
|
};
|
|
401
401
|
|
|
@@ -88,7 +88,7 @@ export class SpacesServiceImpl implements SpacesService {
|
|
|
88
88
|
await space.deactivate();
|
|
89
89
|
break;
|
|
90
90
|
default:
|
|
91
|
-
throw new ApiError('Invalid space state');
|
|
91
|
+
throw new ApiError({ message: 'Invalid space state' });
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
94
|
|
|
@@ -104,9 +104,12 @@ export class SpacesServiceImpl implements SpacesService {
|
|
|
104
104
|
throw new SpaceNotFoundError(request.spaceKey);
|
|
105
105
|
}
|
|
106
106
|
if (!space.spaceState.hasMembershipManagementPermission(identity.identityKey)) {
|
|
107
|
-
throw new AuthorizationError(
|
|
108
|
-
|
|
109
|
-
|
|
107
|
+
throw new AuthorizationError({
|
|
108
|
+
message: 'No member management permission.',
|
|
109
|
+
context: {
|
|
110
|
+
spaceKey: space.key,
|
|
111
|
+
role: space.spaceState.getMemberRole(identity.identityKey),
|
|
112
|
+
},
|
|
110
113
|
});
|
|
111
114
|
}
|
|
112
115
|
const credentials = await createAdmissionCredentials(
|
|
@@ -267,7 +270,7 @@ export class SpacesServiceImpl implements SpacesService {
|
|
|
267
270
|
|
|
268
271
|
async exportSpace(request: ExportSpaceRequest): Promise<ExportSpaceResponse> {
|
|
269
272
|
await using writer = await new SpaceArchiveWriter().open();
|
|
270
|
-
assertArgument(SpaceId.isValid(request.spaceId), 'Invalid space ID');
|
|
273
|
+
assertArgument(SpaceId.isValid(request.spaceId), 'spaceId', 'Invalid space ID');
|
|
271
274
|
|
|
272
275
|
const dataSpaceManager = await this._getDataSpaceManager();
|
|
273
276
|
const space = dataSpaceManager.getSpaceById(request.spaceId) ?? raise(new Error('Space not found'));
|
|
@@ -368,9 +371,9 @@ export class SpacesServiceImpl implements SpacesService {
|
|
|
368
371
|
|
|
369
372
|
private _requireIdentity() {
|
|
370
373
|
if (!this._identityManager.identity) {
|
|
371
|
-
throw new IdentityNotInitializedError(
|
|
372
|
-
'This device has no HALO identity available. See https://docs.dxos.org/guide/platform/halo',
|
|
373
|
-
);
|
|
374
|
+
throw new IdentityNotInitializedError({
|
|
375
|
+
message: 'This device has no HALO identity available. See https://docs.dxos.org/guide/platform/halo',
|
|
376
|
+
});
|
|
374
377
|
}
|
|
375
378
|
return this._identityManager.identity;
|
|
376
379
|
}
|
|
@@ -14,16 +14,16 @@ import StorageDriver = Runtime.Client.Storage.StorageDriver;
|
|
|
14
14
|
export const createStorageObjects = (config: Runtime.Client.Storage) => {
|
|
15
15
|
const { persistent = false, keyStore, dataStore } = config ?? {};
|
|
16
16
|
if (persistent && dataStore === StorageDriver.RAM) {
|
|
17
|
-
throw new InvalidConfigError('RAM storage cannot be used in persistent mode.');
|
|
17
|
+
throw new InvalidConfigError({ message: 'RAM storage cannot be used in persistent mode.' });
|
|
18
18
|
}
|
|
19
19
|
if (!persistent && dataStore !== undefined && dataStore !== StorageDriver.RAM) {
|
|
20
|
-
throw new InvalidConfigError('Cannot use a persistent storage in not persistent mode.');
|
|
20
|
+
throw new InvalidConfigError({ message: 'Cannot use a persistent storage in not persistent mode.' });
|
|
21
21
|
}
|
|
22
22
|
if (persistent && keyStore === StorageDriver.RAM) {
|
|
23
|
-
throw new InvalidConfigError('RAM key storage cannot be used in persistent mode.');
|
|
23
|
+
throw new InvalidConfigError({ message: 'RAM key storage cannot be used in persistent mode.' });
|
|
24
24
|
}
|
|
25
25
|
if (!persistent && keyStore !== StorageDriver.RAM && keyStore !== undefined) {
|
|
26
|
-
throw new InvalidConfigError('Cannot use a persistent key storage in not persistent mode.');
|
|
26
|
+
throw new InvalidConfigError({ message: 'Cannot use a persistent key storage in not persistent mode.' });
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
return {
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const DXOS_VERSION = "0.8.4-main.
|
|
1
|
+
export const DXOS_VERSION = "0.8.4-main.66e292d";
|