@dxos/client-services 0.8.4-main.b97322e → 0.8.4-main.bc674ce

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 (198) hide show
  1. package/dist/lib/browser/{chunk-WKKP35EC.mjs → chunk-J33W6T4Q.mjs} +3625 -3714
  2. package/dist/lib/browser/chunk-J33W6T4Q.mjs.map +7 -0
  3. package/dist/lib/browser/chunk-NQSC7HOE.mjs +22 -0
  4. package/dist/lib/browser/chunk-NQSC7HOE.mjs.map +7 -0
  5. package/dist/lib/browser/chunk-QCWEHHJW.mjs +24 -0
  6. package/dist/lib/browser/chunk-QCWEHHJW.mjs.map +7 -0
  7. package/dist/lib/browser/index.mjs +462 -76
  8. package/dist/lib/browser/index.mjs.map +4 -4
  9. package/dist/lib/browser/meta.json +1 -1
  10. package/dist/lib/browser/packlets/diagnostics/browser-diagnostics-broadcast.mjs +93 -0
  11. package/dist/lib/browser/packlets/diagnostics/browser-diagnostics-broadcast.mjs.map +7 -0
  12. package/dist/lib/browser/packlets/diagnostics/diagnostics-broadcast.mjs +11 -0
  13. package/dist/lib/browser/packlets/diagnostics/diagnostics-broadcast.mjs.map +7 -0
  14. package/dist/lib/browser/packlets/locks/browser.mjs +126 -0
  15. package/dist/lib/browser/packlets/locks/browser.mjs.map +7 -0
  16. package/dist/lib/browser/packlets/locks/node.mjs +66 -0
  17. package/dist/lib/browser/packlets/locks/node.mjs.map +7 -0
  18. package/dist/lib/browser/testing/index.mjs +34 -22
  19. package/dist/lib/browser/testing/index.mjs.map +3 -3
  20. package/dist/lib/node-esm/chunk-2SZHAWBN.mjs +24 -0
  21. package/dist/lib/node-esm/chunk-2SZHAWBN.mjs.map +7 -0
  22. package/dist/lib/node-esm/{chunk-ZE2HYS56.mjs → chunk-34HKLADW.mjs} +2633 -2590
  23. package/dist/lib/node-esm/chunk-34HKLADW.mjs.map +7 -0
  24. package/dist/lib/node-esm/chunk-PKEGMOQ4.mjs +22 -0
  25. package/dist/lib/node-esm/chunk-PKEGMOQ4.mjs.map +7 -0
  26. package/dist/lib/node-esm/index.mjs +462 -76
  27. package/dist/lib/node-esm/index.mjs.map +4 -4
  28. package/dist/lib/node-esm/meta.json +1 -1
  29. package/dist/lib/node-esm/packlets/diagnostics/browser-diagnostics-broadcast.mjs +93 -0
  30. package/dist/lib/node-esm/packlets/diagnostics/browser-diagnostics-broadcast.mjs.map +7 -0
  31. package/dist/lib/node-esm/packlets/diagnostics/diagnostics-broadcast.mjs +11 -0
  32. package/dist/lib/node-esm/packlets/diagnostics/diagnostics-broadcast.mjs.map +7 -0
  33. package/dist/lib/node-esm/packlets/locks/browser.mjs +126 -0
  34. package/dist/lib/node-esm/packlets/locks/browser.mjs.map +7 -0
  35. package/dist/lib/node-esm/packlets/locks/node.mjs +66 -0
  36. package/dist/lib/node-esm/packlets/locks/node.mjs.map +7 -0
  37. package/dist/lib/node-esm/testing/index.mjs +34 -22
  38. package/dist/lib/node-esm/testing/index.mjs.map +3 -3
  39. package/dist/types/src/packlets/agents/edge-agent-service.d.ts +1 -1
  40. package/dist/types/src/packlets/agents/edge-agent-service.d.ts.map +1 -1
  41. package/dist/types/src/packlets/devices/devices-service.d.ts.map +1 -1
  42. package/dist/types/src/packlets/devtools/devtools.d.ts +20 -20
  43. package/dist/types/src/packlets/devtools/devtools.d.ts.map +1 -1
  44. package/dist/types/src/packlets/devtools/feeds.d.ts +1 -1
  45. package/dist/types/src/packlets/devtools/feeds.d.ts.map +1 -1
  46. package/dist/types/src/packlets/devtools/network.d.ts +1 -1
  47. package/dist/types/src/packlets/devtools/network.d.ts.map +1 -1
  48. package/dist/types/src/packlets/diagnostics/browser-diagnostics-broadcast.d.ts +1 -1
  49. package/dist/types/src/packlets/diagnostics/browser-diagnostics-broadcast.d.ts.map +1 -1
  50. package/dist/types/src/packlets/diagnostics/diagnostics-broadcast.d.ts +1 -1
  51. package/dist/types/src/packlets/diagnostics/diagnostics-broadcast.d.ts.map +1 -1
  52. package/dist/types/src/packlets/diagnostics/diagnostics.d.ts +1 -1
  53. package/dist/types/src/packlets/diagnostics/diagnostics.d.ts.map +1 -1
  54. package/dist/types/src/packlets/diagnostics/index.d.ts +1 -1
  55. package/dist/types/src/packlets/diagnostics/index.d.ts.map +1 -1
  56. package/dist/types/src/packlets/identity/authenticator.d.ts +2 -2
  57. package/dist/types/src/packlets/identity/authenticator.d.ts.map +1 -1
  58. package/dist/types/src/packlets/identity/contacts-service.d.ts +1 -1
  59. package/dist/types/src/packlets/identity/contacts-service.d.ts.map +1 -1
  60. package/dist/types/src/packlets/identity/default-space-state-machine.d.ts +3 -3
  61. package/dist/types/src/packlets/identity/default-space-state-machine.d.ts.map +1 -1
  62. package/dist/types/src/packlets/identity/identity-manager.d.ts +5 -5
  63. package/dist/types/src/packlets/identity/identity-manager.d.ts.map +1 -1
  64. package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts +2 -2
  65. package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts.map +1 -1
  66. package/dist/types/src/packlets/identity/identity-service.d.ts +1 -1
  67. package/dist/types/src/packlets/identity/identity-service.d.ts.map +1 -1
  68. package/dist/types/src/packlets/identity/identity.d.ts +3 -3
  69. package/dist/types/src/packlets/identity/identity.d.ts.map +1 -1
  70. package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts +4 -4
  71. package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts.map +1 -1
  72. package/dist/types/src/packlets/invitations/edge-invitation-handler.d.ts +1 -1
  73. package/dist/types/src/packlets/invitations/edge-invitation-handler.d.ts.map +1 -1
  74. package/dist/types/src/packlets/invitations/invitation-guest-extenstion.d.ts.map +1 -1
  75. package/dist/types/src/packlets/invitations/invitation-host-extension.d.ts.map +1 -1
  76. package/dist/types/src/packlets/invitations/invitation-protocol.d.ts +3 -4
  77. package/dist/types/src/packlets/invitations/invitation-protocol.d.ts.map +1 -1
  78. package/dist/types/src/packlets/invitations/invitations-handler.d.ts +4 -4
  79. package/dist/types/src/packlets/invitations/invitations-handler.d.ts.map +1 -1
  80. package/dist/types/src/packlets/invitations/invitations-manager.d.ts.map +1 -1
  81. package/dist/types/src/packlets/invitations/invitations-service.d.ts +1 -1
  82. package/dist/types/src/packlets/invitations/invitations-service.d.ts.map +1 -1
  83. package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts +3 -3
  84. package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts.map +1 -1
  85. package/dist/types/src/packlets/invitations/utils.d.ts.map +1 -1
  86. package/dist/types/src/packlets/locks/index.d.ts +1 -1
  87. package/dist/types/src/packlets/locks/index.d.ts.map +1 -1
  88. package/dist/types/src/packlets/logging/logging-service.d.ts +1 -1
  89. package/dist/types/src/packlets/logging/logging-service.d.ts.map +1 -1
  90. package/dist/types/src/packlets/network/network-service.d.ts +2 -2
  91. package/dist/types/src/packlets/network/network-service.d.ts.map +1 -1
  92. package/dist/types/src/packlets/services/client-rpc-server.d.ts +2 -2
  93. package/dist/types/src/packlets/services/client-rpc-server.d.ts.map +1 -1
  94. package/dist/types/src/packlets/services/service-context.d.ts +14 -8
  95. package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
  96. package/dist/types/src/packlets/services/service-host.d.ts +19 -5
  97. package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
  98. package/dist/types/src/packlets/space-export/space-archive-writer.d.ts +1 -1
  99. package/dist/types/src/packlets/space-export/space-archive-writer.d.ts.map +1 -1
  100. package/dist/types/src/packlets/spaces/automerge-space-state.d.ts +1 -1
  101. package/dist/types/src/packlets/spaces/automerge-space-state.d.ts.map +1 -1
  102. package/dist/types/src/packlets/spaces/data-space-manager.d.ts +12 -7
  103. package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
  104. package/dist/types/src/packlets/spaces/data-space.d.ts +6 -6
  105. package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
  106. package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts +2 -2
  107. package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts.map +1 -1
  108. package/dist/types/src/packlets/spaces/notarization-plugin.d.ts +6 -6
  109. package/dist/types/src/packlets/spaces/notarization-plugin.d.ts.map +1 -1
  110. package/dist/types/src/packlets/spaces/spaces-service.d.ts +2 -2
  111. package/dist/types/src/packlets/spaces/spaces-service.d.ts.map +1 -1
  112. package/dist/types/src/packlets/storage/profile-archive.d.ts.map +1 -1
  113. package/dist/types/src/packlets/storage/storage.d.ts.map +1 -1
  114. package/dist/types/src/packlets/system/system-service.d.ts +1 -1
  115. package/dist/types/src/packlets/system/system-service.d.ts.map +1 -1
  116. package/dist/types/src/packlets/testing/invitation-utils.d.ts +6 -3
  117. package/dist/types/src/packlets/testing/invitation-utils.d.ts.map +1 -1
  118. package/dist/types/src/packlets/testing/test-builder.d.ts +8 -7
  119. package/dist/types/src/packlets/testing/test-builder.d.ts.map +1 -1
  120. package/dist/types/src/packlets/worker/worker-runtime.d.ts +23 -4
  121. package/dist/types/src/packlets/worker/worker-runtime.d.ts.map +1 -1
  122. package/dist/types/src/packlets/worker/worker-session.d.ts +2 -2
  123. package/dist/types/src/packlets/worker/worker-session.d.ts.map +1 -1
  124. package/dist/types/src/version.d.ts +1 -1
  125. package/dist/types/tsconfig.tsbuildinfo +1 -1
  126. package/package.json +72 -48
  127. package/src/packlets/agents/edge-agent-manager.ts +2 -2
  128. package/src/packlets/agents/edge-agent-service.ts +13 -3
  129. package/src/packlets/devices/devices-service.test.ts +4 -3
  130. package/src/packlets/devices/devices-service.ts +2 -2
  131. package/src/packlets/devtools/devtools.ts +30 -29
  132. package/src/packlets/devtools/feeds.ts +2 -2
  133. package/src/packlets/devtools/network.ts +1 -1
  134. package/src/packlets/diagnostics/browser-diagnostics-broadcast.ts +1 -1
  135. package/src/packlets/diagnostics/diagnostics-broadcast.ts +1 -1
  136. package/src/packlets/diagnostics/diagnostics-collector.ts +1 -1
  137. package/src/packlets/diagnostics/diagnostics.ts +1 -1
  138. package/src/packlets/diagnostics/index.ts +1 -1
  139. package/src/packlets/identity/authenticator.node.test.ts +1 -1
  140. package/src/packlets/identity/authenticator.ts +3 -3
  141. package/src/packlets/identity/contacts-service.ts +3 -2
  142. package/src/packlets/identity/default-space-state-machine.ts +3 -3
  143. package/src/packlets/identity/identity-manager.test.ts +3 -3
  144. package/src/packlets/identity/identity-manager.ts +9 -9
  145. package/src/packlets/identity/identity-recovery-manager.ts +2 -2
  146. package/src/packlets/identity/identity-service.test.ts +3 -2
  147. package/src/packlets/identity/identity-service.ts +2 -1
  148. package/src/packlets/identity/identity.test.ts +9 -9
  149. package/src/packlets/identity/identity.ts +9 -8
  150. package/src/packlets/invitations/device-invitation-protocol.test.ts +1 -1
  151. package/src/packlets/invitations/device-invitation-protocol.ts +6 -5
  152. package/src/packlets/invitations/edge-invitation-handler.ts +1 -1
  153. package/src/packlets/invitations/invitation-guest-extenstion.ts +7 -5
  154. package/src/packlets/invitations/invitation-host-extension.ts +8 -6
  155. package/src/packlets/invitations/invitation-protocol.ts +3 -4
  156. package/src/packlets/invitations/invitations-handler.test.ts +4 -3
  157. package/src/packlets/invitations/invitations-handler.ts +10 -10
  158. package/src/packlets/invitations/invitations-manager.ts +3 -3
  159. package/src/packlets/invitations/invitations-service.ts +1 -1
  160. package/src/packlets/invitations/space-invitation-protocol.test.ts +2 -2
  161. package/src/packlets/invitations/space-invitation-protocol.ts +10 -15
  162. package/src/packlets/invitations/utils.ts +1 -1
  163. package/src/packlets/locks/browser.ts +1 -1
  164. package/src/packlets/locks/index.ts +1 -1
  165. package/src/packlets/logging/logging-service.ts +3 -3
  166. package/src/packlets/logging/logging.test.ts +1 -1
  167. package/src/packlets/network/network-service.test.ts +4 -3
  168. package/src/packlets/network/network-service.ts +2 -2
  169. package/src/packlets/services/client-rpc-server.ts +5 -5
  170. package/src/packlets/services/service-context.test.ts +1 -1
  171. package/src/packlets/services/service-context.ts +39 -27
  172. package/src/packlets/services/service-host.test.ts +3 -2
  173. package/src/packlets/services/service-host.ts +72 -24
  174. package/src/packlets/services/service-registry.test.ts +2 -1
  175. package/src/packlets/space-export/space-archive-reader.ts +2 -2
  176. package/src/packlets/space-export/space-archive-writer.ts +7 -5
  177. package/src/packlets/space-export/tar.test.ts +1 -1
  178. package/src/packlets/spaces/automerge-space-state.ts +1 -1
  179. package/src/packlets/spaces/data-space-manager.ts +76 -36
  180. package/src/packlets/spaces/data-space.ts +15 -13
  181. package/src/packlets/spaces/edge-feed-replicator.test.ts +3 -3
  182. package/src/packlets/spaces/edge-feed-replicator.ts +4 -4
  183. package/src/packlets/spaces/epoch-migrations.ts +2 -2
  184. package/src/packlets/spaces/notarization-plugin.test.ts +3 -3
  185. package/src/packlets/spaces/notarization-plugin.ts +11 -11
  186. package/src/packlets/spaces/spaces-service.test.ts +3 -2
  187. package/src/packlets/spaces/spaces-service.ts +27 -23
  188. package/src/packlets/storage/profile-archive.ts +1 -1
  189. package/src/packlets/storage/storage.ts +7 -8
  190. package/src/packlets/system/system-service.test.ts +1 -1
  191. package/src/packlets/system/system-service.ts +4 -4
  192. package/src/packlets/testing/invitation-utils.ts +8 -5
  193. package/src/packlets/testing/test-builder.ts +39 -13
  194. package/src/packlets/worker/worker-runtime.ts +143 -12
  195. package/src/packlets/worker/worker-session.ts +7 -7
  196. package/src/version.ts +1 -1
  197. package/dist/lib/browser/chunk-WKKP35EC.mjs.map +0 -7
  198. package/dist/lib/node-esm/chunk-ZE2HYS56.mjs.map +0 -7
@@ -19,44 +19,45 @@ import { assertArgument, assertState, invariant } from '@dxos/invariant';
19
19
  import { SpaceId } from '@dxos/keys';
20
20
  import { log } from '@dxos/log';
21
21
  import {
22
- encodeError,
23
22
  ApiError,
24
23
  AuthorizationError,
25
24
  IdentityNotInitializedError,
26
25
  SpaceNotFoundError,
26
+ encodeError,
27
27
  } from '@dxos/protocols';
28
28
  import {
29
- SpaceMember,
30
- SpaceState,
29
+ type AdmitContactRequest,
30
+ type ContactAdmission,
31
31
  type CreateEpochRequest,
32
+ type CreateEpochResponse,
33
+ type ExportSpaceRequest,
34
+ type ExportSpaceResponse,
35
+ type ImportSpaceRequest,
36
+ type ImportSpaceResponse,
37
+ type JoinBySpaceKeyRequest,
38
+ type JoinSpaceResponse,
32
39
  type PostMessageRequest,
33
40
  type QueryCredentialsRequest,
34
41
  type QuerySpacesResponse,
35
42
  type Space,
43
+ SpaceMember,
44
+ SpaceState,
36
45
  type SpacesService,
37
46
  type SubscribeMessagesRequest,
47
+ type UpdateMemberRoleRequest,
38
48
  type UpdateSpaceRequest,
39
49
  type WriteCredentialsRequest,
40
- type UpdateMemberRoleRequest,
41
- type AdmitContactRequest,
42
- type ContactAdmission,
43
- type JoinSpaceResponse,
44
- type JoinBySpaceKeyRequest,
45
- type CreateEpochResponse,
46
- type ExportSpaceResponse,
47
- type ExportSpaceRequest,
48
- type ImportSpaceRequest,
49
- type ImportSpaceResponse,
50
50
  } from '@dxos/protocols/proto/dxos/client/services';
51
51
  import { type Credential } from '@dxos/protocols/proto/dxos/halo/credentials';
52
52
  import { type GossipMessage } from '@dxos/protocols/proto/dxos/mesh/teleport/gossip';
53
53
  import { trace } from '@dxos/tracing';
54
54
  import { type Provider } from '@dxos/util';
55
55
 
56
+ import { type IdentityManager } from '../identity';
57
+ import { SpaceArchiveWriter, extractSpaceArchive } from '../space-export';
58
+
56
59
  import { type DataSpace } from './data-space';
57
60
  import { type DataSpaceManager } from './data-space-manager';
58
- import { type IdentityManager } from '../identity';
59
- import { extractSpaceArchive, SpaceArchiveWriter } from '../space-export';
60
61
 
61
62
  export class SpacesServiceImpl implements SpacesService {
62
63
  constructor(
@@ -87,7 +88,7 @@ export class SpacesServiceImpl implements SpacesService {
87
88
  await space.deactivate();
88
89
  break;
89
90
  default:
90
- throw new ApiError('Invalid space state');
91
+ throw new ApiError({ message: 'Invalid space state' });
91
92
  }
92
93
  }
93
94
 
@@ -103,9 +104,12 @@ export class SpacesServiceImpl implements SpacesService {
103
104
  throw new SpaceNotFoundError(request.spaceKey);
104
105
  }
105
106
  if (!space.spaceState.hasMembershipManagementPermission(identity.identityKey)) {
106
- throw new AuthorizationError('No member management permission.', {
107
- spaceKey: space.key,
108
- 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
+ },
109
113
  });
110
114
  }
111
115
  const credentials = await createAdmissionCredentials(
@@ -266,7 +270,7 @@ export class SpacesServiceImpl implements SpacesService {
266
270
 
267
271
  async exportSpace(request: ExportSpaceRequest): Promise<ExportSpaceResponse> {
268
272
  await using writer = await new SpaceArchiveWriter().open();
269
- assertArgument(SpaceId.isValid(request.spaceId), 'Invalid space ID');
273
+ assertArgument(SpaceId.isValid(request.spaceId), 'spaceId', 'Invalid space ID');
270
274
 
271
275
  const dataSpaceManager = await this._getDataSpaceManager();
272
276
  const space = dataSpaceManager.getSpaceById(request.spaceId) ?? raise(new Error('Space not found'));
@@ -367,9 +371,9 @@ export class SpacesServiceImpl implements SpacesService {
367
371
 
368
372
  private _requireIdentity() {
369
373
  if (!this._identityManager.identity) {
370
- throw new IdentityNotInitializedError(
371
- 'This device has no HALO identity available. See https://docs.dxos.org/guide/platform/halo',
372
- );
374
+ throw new IdentityNotInitializedError({
375
+ message: 'This device has no HALO identity available. See https://docs.dxos.org/guide/platform/halo',
376
+ });
373
377
  }
374
378
  return this._identityManager.identity;
375
379
  }
@@ -7,7 +7,7 @@ import { cbor } from '@automerge/automerge-repo';
7
7
  import { invariant } from '@dxos/invariant';
8
8
  import type { LevelDB } from '@dxos/kv-store';
9
9
  import { log } from '@dxos/log';
10
- import { ProfileArchiveEntryType, type ProfileArchive } from '@dxos/protocols';
10
+ import { type ProfileArchive, ProfileArchiveEntryType } from '@dxos/protocols';
11
11
  import type { Storage } from '@dxos/random-access-storage';
12
12
  import { arrayToBuffer } from '@dxos/util';
13
13
 
@@ -1,30 +1,29 @@
1
- //
2
-
3
1
  //
4
2
  // Copyright 2023 DXOS.org
5
3
  //
6
4
 
7
5
  import { InvalidConfigError } from '@dxos/protocols';
8
6
  import { Runtime } from '@dxos/protocols/proto/dxos/config';
9
- import { createStorage, StorageType } from '@dxos/random-access-storage';
7
+ import { StorageType, createStorage } from '@dxos/random-access-storage';
10
8
 
11
- import StorageDriver = Runtime.Client.Storage.StorageDriver;
12
9
  import { getRootPath } from './util';
13
10
 
11
+ import StorageDriver = Runtime.Client.Storage.StorageDriver;
12
+
14
13
  // TODO(burdon): Factor out.
15
14
  export const createStorageObjects = (config: Runtime.Client.Storage) => {
16
15
  const { persistent = false, keyStore, dataStore } = config ?? {};
17
16
  if (persistent && dataStore === StorageDriver.RAM) {
18
- throw new InvalidConfigError('RAM storage cannot be used in persistent mode.');
17
+ throw new InvalidConfigError({ message: 'RAM storage cannot be used in persistent mode.' });
19
18
  }
20
19
  if (!persistent && dataStore !== undefined && dataStore !== StorageDriver.RAM) {
21
- 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.' });
22
21
  }
23
22
  if (persistent && keyStore === StorageDriver.RAM) {
24
- 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.' });
25
24
  }
26
25
  if (!persistent && keyStore !== StorageDriver.RAM && keyStore !== undefined) {
27
- 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.' });
28
27
  }
29
28
 
30
29
  return {
@@ -6,7 +6,7 @@ import { beforeEach, describe, expect, test } from 'vitest';
6
6
 
7
7
  import { Event, Trigger } from '@dxos/async';
8
8
  import { Config } from '@dxos/config';
9
- import { type SystemService, SystemStatus, type QueryStatusResponse } from '@dxos/protocols/proto/dxos/client/services';
9
+ import { type QueryStatusResponse, type SystemService, SystemStatus } from '@dxos/protocols/proto/dxos/client/services';
10
10
 
11
11
  import { SystemServiceImpl } from './system-service';
12
12
 
@@ -7,14 +7,14 @@ import { Stream } from '@dxos/codec-protobuf/stream';
7
7
  import { type Config } from '@dxos/config';
8
8
  import {
9
9
  GetDiagnosticsRequest,
10
+ type Platform,
11
+ type QueryStatusRequest,
12
+ type QueryStatusResponse,
10
13
  type SystemService,
11
14
  type SystemStatus,
12
15
  type UpdateStatusRequest,
13
- type QueryStatusRequest,
14
- type QueryStatusResponse,
15
- type Platform,
16
16
  } from '@dxos/protocols/proto/dxos/client/services';
17
- import { jsonKeyReplacer, type MaybePromise } from '@dxos/util';
17
+ import { type MaybePromise, jsonKeyReplacer } from '@dxos/util';
18
18
 
19
19
  import { type Diagnostics } from '../diagnostics';
20
20
  import { getPlatform } from '../services/platform';
@@ -3,7 +3,7 @@
3
3
  //
4
4
 
5
5
  import { Trigger } from '@dxos/async';
6
- import { InvitationEncoder, type AuthenticatingInvitation, type CancellableInvitation } from '@dxos/client-protocol';
6
+ import { type AuthenticatingInvitation, type CancellableInvitation, InvitationEncoder } from '@dxos/client-protocol';
7
7
  import { invariant } from '@dxos/invariant';
8
8
  import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
9
9
  import { type DeviceProfileDocument } from '@dxos/protocols/proto/dxos/halo/credentials';
@@ -36,15 +36,15 @@ export type PerformInvitationCallbacks<T> = {
36
36
  onError?: (value: T) => boolean | void;
37
37
  };
38
38
 
39
- export type PerformInvitationParams = {
39
+ export type PerformInvitationProps = {
40
40
  host: ServiceContext | InvitationHost;
41
41
  guest: ServiceContext | InvitationGuest;
42
+ guestDeviceProfile?: DeviceProfileDocument;
42
43
  options?: Partial<Invitation>;
43
44
  hooks?: {
44
45
  host?: PerformInvitationCallbacks<CancellableInvitation>;
45
46
  guest?: PerformInvitationCallbacks<AuthenticatingInvitation>;
46
47
  };
47
- guestDeviceProfile?: DeviceProfileDocument;
48
48
  codeInputDelay?: number;
49
49
  };
50
50
 
@@ -52,14 +52,17 @@ export type Result = { invitation?: Invitation; error?: Error };
52
52
 
53
53
  // TODO(burdon): Make async.
54
54
  // TODO(burdon): Rename startInvitation.
55
+ /**
56
+ *
57
+ */
55
58
  export const performInvitation = ({
56
59
  host,
57
60
  guest,
61
+ guestDeviceProfile,
58
62
  options,
59
63
  hooks,
60
- guestDeviceProfile,
61
64
  codeInputDelay,
62
- }: PerformInvitationParams): [Promise<Result>, Promise<Result>] => {
65
+ }: PerformInvitationProps): [Promise<Result>, Promise<Result>] => {
63
66
  let guestError = false;
64
67
  let guestConnected = false;
65
68
  let wereConnected = false;
@@ -2,11 +2,15 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
+ import * as Reactivity from '@effect/experimental/Reactivity';
6
+ import * as Layer from 'effect/Layer';
7
+ import * as ManagedRuntime from 'effect/ManagedRuntime';
8
+
5
9
  import { type Config } from '@dxos/config';
6
10
  import { Context } from '@dxos/context';
7
- import { createCredentialSignerWithChain, CredentialGenerator } from '@dxos/credentials';
11
+ import { CredentialGenerator, createCredentialSignerWithChain } from '@dxos/credentials';
8
12
  import { failUndefined } from '@dxos/debug';
9
- import { EchoHost, MetadataStore, SpaceManager, valueEncoding, MeshEchoReplicator } from '@dxos/echo-pipeline';
13
+ import { EchoHost, MeshEchoReplicator, MetadataStore, SpaceManager, valueEncoding } from '@dxos/echo-pipeline';
10
14
  import { FeedFactory, FeedStore } from '@dxos/feed-store';
11
15
  import { Keyring } from '@dxos/keyring';
12
16
  import { type LevelDB } from '@dxos/kv-store';
@@ -14,12 +18,14 @@ import { createTestLevel } from '@dxos/kv-store/testing';
14
18
  import { MemorySignalManager, MemorySignalManagerContext, type SignalManager } from '@dxos/messaging';
15
19
  import { MemoryTransportFactory, SwarmNetworkManager } from '@dxos/network-manager';
16
20
  import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
17
- import { createStorage, StorageType, type Storage } from '@dxos/random-access-storage';
21
+ import { type Storage, StorageType, createStorage } from '@dxos/random-access-storage';
22
+ import { layerMemory as sqliteLayerMemory } from '@dxos/sql-sqlite/platform';
23
+ import * as SqlTransaction from '@dxos/sql-sqlite/SqlTransaction';
18
24
  import { BlobStore } from '@dxos/teleport-extension-object-sync';
19
25
 
20
26
  import { InvitationsHandler, InvitationsManager, SpaceInvitationProtocol } from '../invitations';
21
- import { ClientServicesHost, ServiceContext, type ServiceContextRuntimeParams } from '../services';
22
- import { DataSpaceManager, type DataSpaceManagerRuntimeParams, type SigningContext } from '../spaces';
27
+ import { ClientServicesHost, ServiceContext, type ServiceContextRuntimeProps } from '../services';
28
+ import { DataSpaceManager, type DataSpaceManagerRuntimeProps, type SigningContext } from '../spaces';
23
29
 
24
30
  //
25
31
  // TODO(burdon): Replace with test builder.
@@ -30,6 +36,11 @@ export const createServiceHost = (config: Config, signalManagerContext: MemorySi
30
36
  config,
31
37
  signalManager: new MemorySignalManager(signalManagerContext),
32
38
  transportFactory: MemoryTransportFactory,
39
+ runtime: ManagedRuntime.make(
40
+ SqlTransaction.layer
41
+ .pipe(Layer.provideMerge(sqliteLayerMemory), Layer.provideMerge(Reactivity.layer))
42
+ .pipe(Layer.orDie),
43
+ ).runtimeEffect,
33
44
  });
34
45
  };
35
46
 
@@ -39,11 +50,11 @@ export const createServiceContext = async ({
39
50
  return new MemorySignalManager(signalContext);
40
51
  },
41
52
  storage = createStorage({ type: StorageType.RAM }),
42
- runtimeParams,
53
+ runtimeProps,
43
54
  }: {
44
55
  signalManagerFactory?: () => Promise<SignalManager>;
45
56
  storage?: Storage;
46
- runtimeParams?: ServiceContextRuntimeParams;
57
+ runtimeProps?: ServiceContextRuntimeProps;
47
58
  } = {}) => {
48
59
  const signalManager = await signalManagerFactory();
49
60
  const networkManager = new SwarmNetworkManager({
@@ -53,9 +64,15 @@ export const createServiceContext = async ({
53
64
  const level = createTestLevel();
54
65
  await level.open();
55
66
 
56
- return new ServiceContext(storage, level, networkManager, signalManager, undefined, undefined, {
57
- invitationConnectionDefaultParams: { teleport: { controlHeartbeatInterval: 200 } },
58
- ...runtimeParams,
67
+ const runtime = ManagedRuntime.make(
68
+ SqlTransaction.layer
69
+ .pipe(Layer.provideMerge(sqliteLayerMemory), Layer.provideMerge(Reactivity.layer))
70
+ .pipe(Layer.orDie),
71
+ ).runtimeEffect;
72
+
73
+ return new ServiceContext(storage, level, networkManager, signalManager, undefined, undefined, runtime, {
74
+ invitationConnectionDefaultProps: { teleport: { controlHeartbeatInterval: 200 } },
75
+ ...runtimeProps,
59
76
  });
60
77
  };
61
78
 
@@ -95,7 +112,7 @@ export class TestBuilder {
95
112
 
96
113
  export type TestPeerOpts = {
97
114
  dataStore?: StorageType;
98
- dataSpaceParams?: DataSpaceManagerRuntimeParams;
115
+ dataSpaceProps?: DataSpaceManagerRuntimeProps;
99
116
  };
100
117
 
101
118
  export type TestPeerProps = {
@@ -116,6 +133,11 @@ export type TestPeerProps = {
116
133
 
117
134
  export class TestPeer {
118
135
  private _props: TestPeerProps = {};
136
+ private readonly _runtime = ManagedRuntime.make(
137
+ SqlTransaction.layer
138
+ .pipe(Layer.provideMerge(sqliteLayerMemory), Layer.provideMerge(Reactivity.layer))
139
+ .pipe(Layer.orDie),
140
+ );
119
141
 
120
142
  constructor(
121
143
  private readonly _signalContext: MemorySignalManagerContext,
@@ -179,7 +201,10 @@ export class TestPeer {
179
201
  }
180
202
 
181
203
  get echoHost() {
182
- return (this._props.echoHost ??= new EchoHost({ kv: this.level }));
204
+ return (this._props.echoHost ??= new EchoHost({
205
+ kv: this.level,
206
+ runtime: this._runtime.runtimeEffect,
207
+ }));
183
208
  }
184
209
 
185
210
  get meshEchoReplicator() {
@@ -198,7 +223,7 @@ export class TestPeer {
198
223
  edgeConnection: undefined,
199
224
  meshReplicator: this.meshEchoReplicator,
200
225
  echoEdgeReplicator: undefined,
201
- runtimeParams: this._opts.dataSpaceParams,
226
+ runtimeProps: this._opts.dataSpaceProps,
202
227
  }));
203
228
  }
204
229
 
@@ -227,6 +252,7 @@ export class TestPeer {
227
252
  async destroy(): Promise<void> {
228
253
  await this.level.close();
229
254
  await this.storage.reset();
255
+ await this._runtime.dispose();
230
256
  }
231
257
  }
232
258
 
@@ -2,6 +2,12 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
+ import * as Reactivity from '@effect/experimental/Reactivity';
6
+ import type * as SqlClient from '@effect/sql/SqlClient';
7
+ import * as Effect from 'effect/Effect';
8
+ import * as Layer from 'effect/Layer';
9
+ import * as ManagedRuntime from 'effect/ManagedRuntime';
10
+
5
11
  import { Trigger } from '@dxos/async';
6
12
  import { DEFAULT_WORKER_BROADCAST_CHANNEL } from '@dxos/client-protocol';
7
13
  import { type Config } from '@dxos/config';
@@ -16,13 +22,18 @@ import {
16
22
  } from '@dxos/messaging';
17
23
  import { RtcTransportProxyFactory } from '@dxos/network-manager';
18
24
  import { type RpcPort } from '@dxos/rpc';
25
+ import * as OpfsWorker from '@dxos/sql-sqlite/OpfsWorker';
26
+ import * as SqlExport from '@dxos/sql-sqlite/SqlExport';
27
+ import * as SqliteClient from '@dxos/sql-sqlite/SqliteClient';
28
+ import * as SqlTransaction from '@dxos/sql-sqlite/SqlTransaction';
19
29
  import { type MaybePromise } from '@dxos/util';
20
30
 
21
- import { WorkerSession } from './worker-session';
22
31
  import { ClientServicesHost } from '../services';
23
32
 
33
+ import { WorkerSession } from './worker-session';
34
+
24
35
  // NOTE: Keep as RpcPorts to avoid dependency on @dxos/rpc-tunnel so we don't depend on browser-specific apis.
25
- export type CreateSessionParams = {
36
+ export type CreateSessionProps = {
26
37
  appPort: RpcPort;
27
38
  systemPort: RpcPort;
28
39
  shellPort?: RpcPort;
@@ -34,10 +45,16 @@ export type WorkerRuntimeOptions = {
34
45
  acquireLock: () => Promise<void>;
35
46
  releaseLock: () => void;
36
47
  onStop?: () => Promise<void>;
48
+ /**
49
+ * @default true
50
+ */
51
+ automaticallyConnectWebrtc?: boolean;
52
+
53
+ enableSqlite?: boolean;
37
54
  };
38
55
 
39
56
  /**
40
- * Runtime for the shared worker.
57
+ * Runtime for the shared and dedciated worker.
41
58
  * Manages connections from proxies (in tabs).
42
59
  * Tabs make requests to the `ClientServicesHost`, and provide a WebRTC gateway.
43
60
  */
@@ -51,11 +68,17 @@ export class WorkerRuntime {
51
68
  private readonly _sessions = new Set<WorkerSession>();
52
69
  private readonly _clientServices!: ClientServicesHost;
53
70
  private readonly _channel: string;
71
+ private readonly _automaticallyConnectWebrtc: boolean;
72
+ private readonly _livenessLock = new WebLockWrapper(`@dxos/client-services/WorkerRuntime/${crypto.randomUUID()}`);
54
73
  private _broadcastChannel?: BroadcastChannel;
55
74
  private _sessionForNetworking?: WorkerSession; // TODO(burdon): Expose to client QueryStatusResponse.
56
75
  private _config!: Config;
57
76
  private _signalMetadataTags: any = { runtime: 'worker-runtime' };
58
77
  private _signalTelemetryEnabled: boolean = false;
78
+ private _runtime!: ManagedRuntime.ManagedRuntime<
79
+ SqlTransaction.SqlTransaction | SqlClient.SqlClient | SqlExport.SqlExport,
80
+ never
81
+ >;
59
82
 
60
83
  constructor({
61
84
  channel = DEFAULT_WORKER_BROADCAST_CHANNEL,
@@ -63,26 +86,47 @@ export class WorkerRuntime {
63
86
  acquireLock,
64
87
  releaseLock,
65
88
  onStop,
89
+ automaticallyConnectWebrtc = true,
90
+ enableSqlite,
66
91
  }: WorkerRuntimeOptions) {
67
92
  this._configProvider = configProvider;
68
93
  this._acquireLock = acquireLock;
69
94
  this._releaseLock = releaseLock;
70
95
  this._onStop = onStop;
71
96
  this._channel = channel;
97
+ this._runtime = ManagedRuntime.make(
98
+ SqlTransaction.layer
99
+ .pipe(Layer.provideMerge(LocalSqliteOpfsLayer), Layer.provideMerge(Reactivity.layer))
100
+ .pipe(Layer.orDie),
101
+ );
72
102
  this._clientServices = new ClientServicesHost({
73
103
  callbacks: {
74
104
  onReset: async () => this.stop(),
75
105
  },
106
+ runtime: this._runtime.runtimeEffect,
107
+ runtimeProps: {
108
+ enableSqlite,
109
+ // Auto-activate spaces that were previously active after leader changeover.
110
+ autoActivateSpaces: true,
111
+ },
76
112
  });
113
+ this._automaticallyConnectWebrtc = automaticallyConnectWebrtc;
77
114
  }
78
115
 
79
116
  get host() {
80
117
  return this._clientServices;
81
118
  }
82
119
 
120
+ get livenessLockKey(): string {
121
+ return this._livenessLock.key;
122
+ }
123
+
83
124
  async start(): Promise<void> {
84
125
  log('starting...');
85
126
  try {
127
+ void this._livenessLock.acquire();
128
+
129
+ // Steal the lock from the other worker.
86
130
  this._broadcastChannel = new BroadcastChannel(this._channel);
87
131
  this._broadcastChannel.postMessage({ action: 'stop' });
88
132
  this._broadcastChannel.onmessage = async (event) => {
@@ -126,13 +170,15 @@ export class WorkerRuntime {
126
170
  this._broadcastChannel?.close();
127
171
  this._broadcastChannel = undefined;
128
172
  await this._clientServices.close();
173
+ await this._runtime.dispose();
129
174
  await this._onStop?.();
175
+ await this._livenessLock.release();
130
176
  }
131
177
 
132
178
  /**
133
179
  * Create a new session.
134
180
  */
135
- async createSession({ appPort, systemPort, shellPort }: CreateSessionParams): Promise<void> {
181
+ async createSession({ appPort, systemPort, shellPort }: CreateSessionProps): Promise<WorkerSession> {
136
182
  const session = new WorkerSession({
137
183
  serviceHost: this._clientServices,
138
184
  appPort,
@@ -148,7 +194,9 @@ export class WorkerRuntime {
148
194
  // Terminate the worker when all sessions are closed.
149
195
  await this.stop();
150
196
  } else {
151
- this._reconnectWebrtc();
197
+ if (this._automaticallyConnectWebrtc) {
198
+ this._reconnectWebrtc();
199
+ }
152
200
  }
153
201
  });
154
202
 
@@ -165,7 +213,24 @@ export class WorkerRuntime {
165
213
  this._signalMetadataTags.origin = session.origin;
166
214
  this._sessions.add(session);
167
215
 
168
- this._reconnectWebrtc();
216
+ if (this._automaticallyConnectWebrtc) {
217
+ this._reconnectWebrtc();
218
+ }
219
+
220
+ return session;
221
+ }
222
+
223
+ /**
224
+ * Connects the WebRTC bridge to the specified session.
225
+ * If no session is provided, disconnects the WebRTC bridge.
226
+ *
227
+ * Called automatically if `automaticallyConnectWebrtc` is true.
228
+ *
229
+ * @param session The session to connect the WebRTC bridge to.
230
+ */
231
+ connectWebrtcBridge(session: WorkerSession | undefined): void {
232
+ this._sessionForNetworking = session;
233
+ this._transportFactory.setBridgeService(session?.bridgeService);
169
234
  }
170
235
 
171
236
  /**
@@ -183,12 +248,78 @@ export class WorkerRuntime {
183
248
  // Select existing session.
184
249
  if (!this._sessionForNetworking) {
185
250
  const selected = Array.from(this._sessions).find((session) => session.bridgeService);
186
- if (selected) {
187
- this._sessionForNetworking = selected;
188
- this._transportFactory.setBridgeService(selected.bridgeService);
189
- } else {
190
- this._transportFactory.setBridgeService(undefined);
191
- }
251
+ this.connectWebrtcBridge(selected);
192
252
  }
193
253
  }
194
254
  }
255
+
256
+ const DB_NAME = 'DXOS';
257
+
258
+ /**
259
+ * SqlExport layer that wraps SqliteClient to provide export functionality.
260
+ */
261
+ const SqlExportLayer: Layer.Layer<SqlExport.SqlExport, never, SqliteClient.SqliteClient> = Layer.effect(
262
+ SqlExport.SqlExport,
263
+ Effect.gen(function* () {
264
+ const sql = yield* SqliteClient.SqliteClient;
265
+ return {
266
+ export: sql.export,
267
+ } satisfies SqlExport.Service;
268
+ }),
269
+ );
270
+
271
+ /**
272
+ * Local SQLite layer for the worker.
273
+ * Uses OPFS sync API as an FS backend.
274
+ * Does NOT spawn a new worker.
275
+ * NOTE: Only usable within a worker.
276
+ * TODO(mykola): This does not work right now. Fix.
277
+ */
278
+ const LocalSqliteOpfsLayer = Layer.unwrapScoped(
279
+ Effect.gen(function* () {
280
+ const { port1: clientPort, port2: serverPort } = new MessageChannel();
281
+ clientPort.start();
282
+ serverPort.start();
283
+ yield* Effect.addFinalizer(() =>
284
+ Effect.sync(() => {
285
+ clientPort.close();
286
+ serverPort.close();
287
+ }),
288
+ );
289
+
290
+ yield* Effect.forkScoped(OpfsWorker.run({ port: serverPort, dbName: DB_NAME }));
291
+ return SqlExportLayer.pipe(Layer.provideMerge(SqliteClient.layer({ worker: Effect.succeed(clientPort) })));
292
+ }),
293
+ );
294
+
295
+ // TODO(wittjosiah): Factor out to a separate module.
296
+ class WebLockWrapper {
297
+ readonly #key: string;
298
+ #release?: () => void;
299
+
300
+ constructor(key: string) {
301
+ this.#key = key;
302
+ }
303
+
304
+ get key(): string {
305
+ return this.#key;
306
+ }
307
+
308
+ acquire(options: LockOptions = {}) {
309
+ return navigator.locks.request(this.#key, options, async () => {
310
+ await new Promise<void>((resolve) => {
311
+ this.#release = resolve;
312
+ }); // Blocks for the duration of the worker's lifetime.
313
+ this.#release = undefined;
314
+ });
315
+ }
316
+
317
+ release() {
318
+ this.#release?.();
319
+ this.#release = undefined;
320
+ }
321
+
322
+ [Symbol.dispose]() {
323
+ this.release();
324
+ }
325
+ }
@@ -2,22 +2,22 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
- import { asyncTimeout, Trigger } from '@dxos/async';
5
+ import { Trigger, asyncTimeout } from '@dxos/async';
6
6
  import {
7
- iframeServiceBundle,
8
7
  type IframeServiceBundle,
9
8
  PROXY_CONNECTION_TIMEOUT,
9
+ iframeServiceBundle,
10
10
  workerServiceBundle,
11
11
  } from '@dxos/client-protocol';
12
12
  import { invariant } from '@dxos/invariant';
13
13
  import { log, logInfo } from '@dxos/log';
14
14
  import { type BridgeService } from '@dxos/protocols/proto/dxos/mesh/bridge';
15
- import { createProtoRpcPeer, type ProtoRpcPeer, type RpcPort } from '@dxos/rpc';
15
+ import { type ProtoRpcPeer, type RpcPort, createProtoRpcPeer } from '@dxos/rpc';
16
16
  import { Callback, type MaybePromise } from '@dxos/util';
17
17
 
18
- import { type ClientServicesHost, ClientRpcServer, type ClientRpcServerParams } from '../services';
18
+ import { ClientRpcServer, type ClientRpcServerProps, type ClientServicesHost } from '../services';
19
19
 
20
- export type WorkerSessionParams = {
20
+ export type WorkerSessionProps = {
21
21
  serviceHost: ClientServicesHost;
22
22
  systemPort: RpcPort;
23
23
  appPort: RpcPort;
@@ -50,11 +50,11 @@ export class WorkerSession {
50
50
 
51
51
  public bridgeService?: BridgeService;
52
52
 
53
- constructor({ serviceHost, systemPort, appPort, shellPort, readySignal }: WorkerSessionParams) {
53
+ constructor({ serviceHost, systemPort, appPort, shellPort, readySignal }: WorkerSessionProps) {
54
54
  invariant(serviceHost);
55
55
  this._serviceHost = serviceHost;
56
56
 
57
- const middleware: Pick<ClientRpcServerParams, 'handleCall' | 'handleStream'> = {
57
+ const middleware: Pick<ClientRpcServerProps, 'handleCall' | 'handleStream'> = {
58
58
  handleCall: async (method, params, handler) => {
59
59
  const error = await readySignal.wait({ timeout: PROXY_CONNECTION_TIMEOUT });
60
60
  if (error) {
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const DXOS_VERSION = "0.8.4-main.b97322e";
1
+ export const DXOS_VERSION = "0.8.4-main.bc674ce";