@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.
Files changed (53) hide show
  1. package/dist/lib/browser/{chunk-JBVOLD57.mjs → chunk-PWKWJATU.mjs} +899 -1209
  2. package/dist/lib/browser/chunk-PWKWJATU.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +110 -135
  4. package/dist/lib/browser/index.mjs.map +2 -2
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/testing/index.mjs +37 -66
  7. package/dist/lib/browser/testing/index.mjs.map +2 -2
  8. package/dist/lib/node-esm/{chunk-AADRC6MD.mjs → chunk-7NQQ5F2Q.mjs} +900 -1210
  9. package/dist/lib/node-esm/chunk-7NQQ5F2Q.mjs.map +7 -0
  10. package/dist/lib/node-esm/index.mjs +110 -135
  11. package/dist/lib/node-esm/index.mjs.map +2 -2
  12. package/dist/lib/node-esm/meta.json +1 -1
  13. package/dist/lib/node-esm/testing/index.mjs +37 -66
  14. package/dist/lib/node-esm/testing/index.mjs.map +2 -2
  15. package/dist/types/src/packlets/agents/edge-agent-service.d.ts.map +1 -1
  16. package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts +2 -2
  17. package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts.map +1 -1
  18. package/dist/types/src/packlets/invitations/invitation-guest-extenstion.d.ts.map +1 -1
  19. package/dist/types/src/packlets/invitations/invitation-host-extension.d.ts.map +1 -1
  20. package/dist/types/src/packlets/invitations/invitation-protocol.d.ts +2 -3
  21. package/dist/types/src/packlets/invitations/invitation-protocol.d.ts.map +1 -1
  22. package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts +2 -2
  23. package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts.map +1 -1
  24. package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
  25. package/dist/types/src/packlets/space-export/space-archive-writer.d.ts.map +1 -1
  26. package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
  27. package/dist/types/src/packlets/spaces/spaces-service.d.ts.map +1 -1
  28. package/dist/types/src/version.d.ts +1 -1
  29. package/dist/types/tsconfig.tsbuildinfo +1 -1
  30. package/package.json +39 -39
  31. package/src/packlets/agents/edge-agent-service.ts +11 -1
  32. package/src/packlets/devices/devices-service.ts +1 -1
  33. package/src/packlets/identity/identity.test.ts +4 -4
  34. package/src/packlets/invitations/device-invitation-protocol.ts +3 -3
  35. package/src/packlets/invitations/invitation-guest-extenstion.ts +6 -4
  36. package/src/packlets/invitations/invitation-host-extension.ts +6 -4
  37. package/src/packlets/invitations/invitation-protocol.ts +2 -3
  38. package/src/packlets/invitations/invitations-handler.ts +1 -1
  39. package/src/packlets/invitations/space-invitation-protocol.ts +7 -13
  40. package/src/packlets/logging/logging-service.ts +1 -1
  41. package/src/packlets/services/service-host.ts +6 -0
  42. package/src/packlets/space-export/space-archive-reader.ts +2 -2
  43. package/src/packlets/space-export/space-archive-writer.ts +4 -3
  44. package/src/packlets/spaces/data-space-manager.ts +28 -8
  45. package/src/packlets/spaces/data-space.ts +1 -1
  46. package/src/packlets/spaces/edge-feed-replicator.test.ts +1 -1
  47. package/src/packlets/spaces/edge-feed-replicator.ts +1 -1
  48. package/src/packlets/spaces/notarization-plugin.ts +2 -2
  49. package/src/packlets/spaces/spaces-service.ts +11 -8
  50. package/src/packlets/storage/storage.ts +4 -4
  51. package/src/version.ts +1 -1
  52. package/dist/lib/browser/chunk-JBVOLD57.mjs.map +0 -7
  53. 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.5ea62a8",
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.1",
47
- "@automerge/automerge-repo": "2.3.0-alpha.0",
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.5ea62a8",
52
- "@dxos/codec-protobuf": "0.8.4-main.5ea62a8",
53
- "@dxos/client-protocol": "0.8.4-main.5ea62a8",
54
- "@dxos/context": "0.8.4-main.5ea62a8",
55
- "@dxos/credentials": "0.8.4-main.5ea62a8",
56
- "@dxos/debug": "0.8.4-main.5ea62a8",
57
- "@dxos/crypto": "0.8.4-main.5ea62a8",
58
- "@dxos/config": "0.8.4-main.5ea62a8",
59
- "@dxos/echo-pipeline": "0.8.4-main.5ea62a8",
60
- "@dxos/echo-protocol": "0.8.4-main.5ea62a8",
61
- "@dxos/edge-client": "0.8.4-main.5ea62a8",
62
- "@dxos/echo-schema": "0.8.4-main.5ea62a8",
63
- "@dxos/indexing": "0.8.4-main.5ea62a8",
64
- "@dxos/echo-db": "0.8.4-main.5ea62a8",
65
- "@dxos/invariant": "0.8.4-main.5ea62a8",
66
- "@dxos/keyring": "0.8.4-main.5ea62a8",
67
- "@dxos/kv-store": "0.8.4-main.5ea62a8",
68
- "@dxos/keys": "0.8.4-main.5ea62a8",
69
- "@dxos/lock-file": "0.8.4-main.5ea62a8",
70
- "@dxos/log": "0.8.4-main.5ea62a8",
71
- "@dxos/messaging": "0.8.4-main.5ea62a8",
72
- "@dxos/network-manager": "0.8.4-main.5ea62a8",
73
- "@dxos/node-std": "0.8.4-main.5ea62a8",
74
- "@dxos/protocols": "0.8.4-main.5ea62a8",
75
- "@dxos/random-access-storage": "0.8.4-main.5ea62a8",
76
- "@dxos/teleport": "0.8.4-main.5ea62a8",
77
- "@dxos/teleport-extension-gossip": "0.8.4-main.5ea62a8",
78
- "@dxos/rpc": "0.8.4-main.5ea62a8",
79
- "@dxos/teleport-extension-object-sync": "0.8.4-main.5ea62a8",
80
- "@dxos/timeframe": "0.8.4-main.5ea62a8",
81
- "@dxos/tracing": "0.8.4-main.5ea62a8",
82
- "@dxos/util": "0.8.4-main.5ea62a8",
83
- "@dxos/websocket-rpc": "0.8.4-main.5ea62a8",
84
- "@dxos/feed-store": "0.8.4-main.5ea62a8"
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/signal": "0.8.4-main.5ea62a8",
91
- "@dxos/test-utils": "0.8.4-main.5ea62a8"
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({ status: this._edgeConnection?.status ?? EdgeStatus.NOT_CONNECTED });
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, type ApiError } from '@dxos/protocols';
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(): ApiError | undefined {
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(undefined, {
101
- expected: InvitationOptions.Role.HOST,
102
- remoteOptions: this._remoteOptions,
103
- remotePeerId: context.remotePeerId,
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(undefined, {
249
- expected: InvitationOptions.Role.GUEST,
250
- remoteOptions: this._remoteOptions,
251
- remotePeerId: context.remotePeerId,
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(): ApiError | undefined;
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>): ApiError | undefined;
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(): ApiError | undefined {
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.info('extracted space archive', { metadata, documents });
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
- filename: `${this._meta.spaceId}.tar`,
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 { PropertiesType, TYPE_PROPERTIES } from '@dxos/client-protocol';
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, TYPE_PROPERTIES);
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(!!options.rootUrl === !!options.documents, 'root url must be required when providing documents');
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
- const newDoc = await this._echoHost.createDoc(data, { preserveHistory: true });
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
- const [_, properties] = findInlineObjectOfType(space.databaseRoot.doc()!, TYPE_PROPERTIES) ?? [];
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(PropertiesType)!),
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.errorData) {
395
+ if (!(error instanceof EdgeCallFailedError) || error.data) {
396
396
  log.catch(error);
397
397
  } else {
398
- log.info('Edge notarization failure', { reason: error.reason });
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('No member management permission.', {
108
- spaceKey: space.key,
109
- role: space.spaceState.getMemberRole(identity.identityKey),
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.5ea62a8";
1
+ export const DXOS_VERSION = "0.8.4-main.66e292d";