@dxos/client-services 0.8.4-main.a4bbb77 → 0.8.4-main.abd8ff62ef

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 (229) hide show
  1. package/dist/lib/browser/{chunk-FZDVFED2.mjs → chunk-KW4WMU5R.mjs} +2698 -4599
  2. package/dist/lib/browser/chunk-KW4WMU5R.mjs.map +7 -0
  3. package/dist/lib/browser/chunk-QCWEHHJW.mjs +24 -0
  4. package/dist/lib/browser/chunk-QCWEHHJW.mjs.map +7 -0
  5. package/dist/lib/browser/chunk-XJRPB3GA.mjs +22 -0
  6. package/dist/lib/browser/chunk-XJRPB3GA.mjs.map +7 -0
  7. package/dist/lib/browser/index.mjs +490 -228
  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 +88 -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 +86 -0
  15. package/dist/lib/browser/packlets/locks/browser.mjs.map +7 -0
  16. package/dist/lib/browser/packlets/locks/node.mjs +48 -0
  17. package/dist/lib/browser/packlets/locks/node.mjs.map +7 -0
  18. package/dist/lib/browser/testing/index.mjs +60 -90
  19. package/dist/lib/browser/testing/index.mjs.map +3 -3
  20. package/dist/lib/node-esm/chunk-2DT3MZRL.mjs +22 -0
  21. package/dist/lib/node-esm/chunk-2DT3MZRL.mjs.map +7 -0
  22. package/dist/lib/node-esm/chunk-2SZHAWBN.mjs +24 -0
  23. package/dist/lib/node-esm/chunk-2SZHAWBN.mjs.map +7 -0
  24. package/dist/lib/node-esm/{chunk-JDTIU3EP.mjs → chunk-NDMKP2CH.mjs} +2621 -4391
  25. package/dist/lib/node-esm/chunk-NDMKP2CH.mjs.map +7 -0
  26. package/dist/lib/node-esm/index.mjs +490 -228
  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 +88 -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 +86 -0
  34. package/dist/lib/node-esm/packlets/locks/browser.mjs.map +7 -0
  35. package/dist/lib/node-esm/packlets/locks/node.mjs +48 -0
  36. package/dist/lib/node-esm/packlets/locks/node.mjs.map +7 -0
  37. package/dist/lib/node-esm/testing/index.mjs +60 -90
  38. package/dist/lib/node-esm/testing/index.mjs.map +3 -3
  39. package/dist/types/src/index.d.ts +1 -0
  40. package/dist/types/src/index.d.ts.map +1 -1
  41. package/dist/types/src/packlets/agents/edge-agent-manager.d.ts +3 -2
  42. package/dist/types/src/packlets/agents/edge-agent-manager.d.ts.map +1 -1
  43. package/dist/types/src/packlets/agents/edge-agent-service.d.ts +2 -1
  44. package/dist/types/src/packlets/agents/edge-agent-service.d.ts.map +1 -1
  45. package/dist/types/src/packlets/devices/devices-service.d.ts.map +1 -1
  46. package/dist/types/src/packlets/devtools/devtools.d.ts +2 -2
  47. package/dist/types/src/packlets/devtools/devtools.d.ts.map +1 -1
  48. package/dist/types/src/packlets/devtools/feeds.d.ts.map +1 -1
  49. package/dist/types/src/packlets/devtools/keys.d.ts.map +1 -1
  50. package/dist/types/src/packlets/devtools/metadata.d.ts.map +1 -1
  51. package/dist/types/src/packlets/devtools/network.d.ts.map +1 -1
  52. package/dist/types/src/packlets/devtools/spaces.d.ts.map +1 -1
  53. package/dist/types/src/packlets/diagnostics/browser-diagnostics-broadcast.d.ts.map +1 -1
  54. package/dist/types/src/packlets/diagnostics/diagnostics-broadcast.d.ts.map +1 -1
  55. package/dist/types/src/packlets/diagnostics/diagnostics-collector.d.ts.map +1 -1
  56. package/dist/types/src/packlets/diagnostics/diagnostics.d.ts +2 -3
  57. package/dist/types/src/packlets/diagnostics/diagnostics.d.ts.map +1 -1
  58. package/dist/types/src/packlets/diagnostics/index.d.ts +1 -1
  59. package/dist/types/src/packlets/diagnostics/index.d.ts.map +1 -1
  60. package/dist/types/src/packlets/identity/authenticator.d.ts +2 -2
  61. package/dist/types/src/packlets/identity/authenticator.d.ts.map +1 -1
  62. package/dist/types/src/packlets/identity/contacts-service.d.ts.map +1 -1
  63. package/dist/types/src/packlets/identity/identity-manager.d.ts +6 -6
  64. package/dist/types/src/packlets/identity/identity-manager.d.ts.map +1 -1
  65. package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts +8 -7
  66. package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts.map +1 -1
  67. package/dist/types/src/packlets/identity/identity-service.d.ts +6 -10
  68. package/dist/types/src/packlets/identity/identity-service.d.ts.map +1 -1
  69. package/dist/types/src/packlets/identity/identity.d.ts +8 -11
  70. package/dist/types/src/packlets/identity/identity.d.ts.map +1 -1
  71. package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts +6 -5
  72. package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts.map +1 -1
  73. package/dist/types/src/packlets/invitations/edge-invitation-handler.d.ts +1 -1
  74. package/dist/types/src/packlets/invitations/edge-invitation-handler.d.ts.map +1 -1
  75. package/dist/types/src/packlets/invitations/invitation-guest-extenstion.d.ts.map +1 -1
  76. package/dist/types/src/packlets/invitations/invitation-host-extension.d.ts.map +1 -1
  77. package/dist/types/src/packlets/invitations/invitation-protocol.d.ts +7 -4
  78. package/dist/types/src/packlets/invitations/invitation-protocol.d.ts.map +1 -1
  79. package/dist/types/src/packlets/invitations/invitation-state.d.ts.map +1 -1
  80. package/dist/types/src/packlets/invitations/invitation-topology.d.ts.map +1 -1
  81. package/dist/types/src/packlets/invitations/invitations-handler.d.ts +4 -4
  82. package/dist/types/src/packlets/invitations/invitations-handler.d.ts.map +1 -1
  83. package/dist/types/src/packlets/invitations/invitations-manager.d.ts +3 -3
  84. package/dist/types/src/packlets/invitations/invitations-manager.d.ts.map +1 -1
  85. package/dist/types/src/packlets/invitations/invitations-service.d.ts +3 -3
  86. package/dist/types/src/packlets/invitations/invitations-service.d.ts.map +1 -1
  87. package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts +4 -3
  88. package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts.map +1 -1
  89. package/dist/types/src/packlets/invitations/utils.d.ts.map +1 -1
  90. package/dist/types/src/packlets/locks/browser.d.ts.map +1 -1
  91. package/dist/types/src/packlets/locks/index.d.ts +1 -1
  92. package/dist/types/src/packlets/locks/index.d.ts.map +1 -1
  93. package/dist/types/src/packlets/locks/node.d.ts.map +1 -1
  94. package/dist/types/src/packlets/logging/logging-service.d.ts +4 -0
  95. package/dist/types/src/packlets/logging/logging-service.d.ts.map +1 -1
  96. package/dist/types/src/packlets/network/network-service.d.ts +5 -4
  97. package/dist/types/src/packlets/network/network-service.d.ts.map +1 -1
  98. package/dist/types/src/packlets/services/client-rpc-server.d.ts +5 -5
  99. package/dist/types/src/packlets/services/client-rpc-server.d.ts.map +1 -1
  100. package/dist/types/src/packlets/services/feed-syncer.d.ts +59 -0
  101. package/dist/types/src/packlets/services/feed-syncer.d.ts.map +1 -0
  102. package/dist/types/src/packlets/services/feed-syncer.test.d.ts +2 -0
  103. package/dist/types/src/packlets/services/feed-syncer.test.d.ts.map +1 -0
  104. package/dist/types/src/packlets/services/platform.d.ts.map +1 -1
  105. package/dist/types/src/packlets/services/service-context.d.ts +13 -9
  106. package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
  107. package/dist/types/src/packlets/services/service-host.d.ts +20 -7
  108. package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
  109. package/dist/types/src/packlets/services/service-registry.d.ts.map +1 -1
  110. package/dist/types/src/packlets/services/util.d.ts.map +1 -1
  111. package/dist/types/src/packlets/space-export/archive-format.d.ts +9 -0
  112. package/dist/types/src/packlets/space-export/archive-format.d.ts.map +1 -0
  113. package/dist/types/src/packlets/space-export/index.d.ts +4 -1
  114. package/dist/types/src/packlets/space-export/index.d.ts.map +1 -1
  115. package/dist/types/src/packlets/space-export/serialized-space-reader.d.ts +23 -0
  116. package/dist/types/src/packlets/space-export/serialized-space-reader.d.ts.map +1 -0
  117. package/dist/types/src/packlets/space-export/serialized-space-writer.d.ts +36 -0
  118. package/dist/types/src/packlets/space-export/serialized-space-writer.d.ts.map +1 -0
  119. package/dist/types/src/packlets/space-export/space-archive-reader.d.ts +9 -1
  120. package/dist/types/src/packlets/space-export/space-archive-reader.d.ts.map +1 -1
  121. package/dist/types/src/packlets/space-export/space-archive-writer.d.ts +7 -1
  122. package/dist/types/src/packlets/space-export/space-archive-writer.d.ts.map +1 -1
  123. package/dist/types/src/packlets/space-export/space-archive.test.d.ts +2 -0
  124. package/dist/types/src/packlets/space-export/space-archive.test.d.ts.map +1 -0
  125. package/dist/types/src/packlets/spaces/automerge-space-state.d.ts.map +1 -1
  126. package/dist/types/src/packlets/spaces/data-space-manager.d.ts +28 -17
  127. package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
  128. package/dist/types/src/packlets/spaces/data-space.d.ts +26 -9
  129. package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
  130. package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts +2 -2
  131. package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts.map +1 -1
  132. package/dist/types/src/packlets/spaces/epoch-migrations.d.ts.map +1 -1
  133. package/dist/types/src/packlets/spaces/genesis.d.ts +2 -1
  134. package/dist/types/src/packlets/spaces/genesis.d.ts.map +1 -1
  135. package/dist/types/src/packlets/spaces/notarization-plugin.d.ts +6 -9
  136. package/dist/types/src/packlets/spaces/notarization-plugin.d.ts.map +1 -1
  137. package/dist/types/src/packlets/spaces/spaces-service.d.ts +10 -7
  138. package/dist/types/src/packlets/spaces/spaces-service.d.ts.map +1 -1
  139. package/dist/types/src/packlets/storage/level.d.ts.map +1 -1
  140. package/dist/types/src/packlets/storage/profile-archive.d.ts.map +1 -1
  141. package/dist/types/src/packlets/storage/storage.d.ts.map +1 -1
  142. package/dist/types/src/packlets/storage/util.d.ts.map +1 -1
  143. package/dist/types/src/packlets/system/system-service.d.ts +1 -1
  144. package/dist/types/src/packlets/system/system-service.d.ts.map +1 -1
  145. package/dist/types/src/packlets/testing/credential-utils.d.ts.map +1 -1
  146. package/dist/types/src/packlets/testing/invitation-utils.d.ts +6 -3
  147. package/dist/types/src/packlets/testing/invitation-utils.d.ts.map +1 -1
  148. package/dist/types/src/packlets/testing/test-builder.d.ts +6 -5
  149. package/dist/types/src/packlets/testing/test-builder.d.ts.map +1 -1
  150. package/dist/types/src/packlets/worker/worker-runtime.d.ts +41 -4
  151. package/dist/types/src/packlets/worker/worker-runtime.d.ts.map +1 -1
  152. package/dist/types/src/packlets/worker/worker-session.d.ts +2 -4
  153. package/dist/types/src/packlets/worker/worker-session.d.ts.map +1 -1
  154. package/dist/types/src/testing/setup.d.ts.map +1 -1
  155. package/dist/types/src/version.d.ts +1 -1
  156. package/dist/types/src/version.d.ts.map +1 -1
  157. package/dist/types/tsconfig.tsbuildinfo +1 -1
  158. package/package.json +70 -55
  159. package/src/index.ts +1 -0
  160. package/src/packlets/agents/edge-agent-manager.ts +8 -5
  161. package/src/packlets/agents/edge-agent-service.ts +15 -3
  162. package/src/packlets/devices/devices-service.test.ts +0 -1
  163. package/src/packlets/devices/devices-service.ts +1 -1
  164. package/src/packlets/devtools/devtools.ts +2 -3
  165. package/src/packlets/diagnostics/diagnostics.ts +1 -2
  166. package/src/packlets/diagnostics/index.ts +1 -1
  167. package/src/packlets/identity/authenticator.ts +2 -2
  168. package/src/packlets/identity/contacts-service.ts +0 -1
  169. package/src/packlets/identity/identity-manager.test.ts +5 -5
  170. package/src/packlets/identity/identity-manager.ts +23 -22
  171. package/src/packlets/identity/identity-recovery-manager.ts +22 -18
  172. package/src/packlets/identity/identity-service.test.ts +6 -27
  173. package/src/packlets/identity/identity-service.ts +13 -81
  174. package/src/packlets/identity/identity.test.ts +6 -6
  175. package/src/packlets/identity/identity.ts +11 -34
  176. package/src/packlets/invitations/device-invitation-protocol.ts +8 -7
  177. package/src/packlets/invitations/edge-invitation-handler.ts +9 -5
  178. package/src/packlets/invitations/invitation-guest-extenstion.ts +6 -4
  179. package/src/packlets/invitations/invitation-host-extension.ts +13 -14
  180. package/src/packlets/invitations/invitation-protocol.ts +7 -4
  181. package/src/packlets/invitations/invitation-state.ts +1 -15
  182. package/src/packlets/invitations/invitations-handler.test.ts +4 -5
  183. package/src/packlets/invitations/invitations-handler.ts +74 -22
  184. package/src/packlets/invitations/invitations-manager.ts +40 -15
  185. package/src/packlets/invitations/invitations-service.ts +9 -9
  186. package/src/packlets/invitations/space-invitation-protocol.test.ts +17 -16
  187. package/src/packlets/invitations/space-invitation-protocol.ts +11 -16
  188. package/src/packlets/locks/index.ts +1 -1
  189. package/src/packlets/logging/logging-service.ts +20 -16
  190. package/src/packlets/network/network-service.test.ts +0 -1
  191. package/src/packlets/network/network-service.ts +10 -8
  192. package/src/packlets/services/client-rpc-server.ts +19 -16
  193. package/src/packlets/services/feed-syncer.test.ts +340 -0
  194. package/src/packlets/services/feed-syncer.ts +337 -0
  195. package/src/packlets/services/platform.ts +7 -1
  196. package/src/packlets/services/service-context.test.ts +3 -2
  197. package/src/packlets/services/service-context.ts +138 -56
  198. package/src/packlets/services/service-host.test.ts +8 -8
  199. package/src/packlets/services/service-host.ts +70 -40
  200. package/src/packlets/services/service-registry.test.ts +0 -1
  201. package/src/packlets/space-export/archive-format.ts +42 -0
  202. package/src/packlets/space-export/index.ts +4 -1
  203. package/src/packlets/space-export/serialized-space-reader.ts +111 -0
  204. package/src/packlets/space-export/serialized-space-writer.ts +253 -0
  205. package/src/packlets/space-export/space-archive-reader.ts +64 -3
  206. package/src/packlets/space-export/space-archive-writer.ts +41 -3
  207. package/src/packlets/space-export/space-archive.test.ts +461 -0
  208. package/src/packlets/spaces/data-space-manager.test.ts +79 -13
  209. package/src/packlets/spaces/data-space-manager.ts +115 -115
  210. package/src/packlets/spaces/data-space.ts +58 -33
  211. package/src/packlets/spaces/edge-feed-replicator.test.ts +2 -2
  212. package/src/packlets/spaces/edge-feed-replicator.ts +12 -10
  213. package/src/packlets/spaces/epoch-migrations.ts +5 -5
  214. package/src/packlets/spaces/genesis.ts +6 -1
  215. package/src/packlets/spaces/notarization-plugin.test.ts +2 -2
  216. package/src/packlets/spaces/notarization-plugin.ts +10 -9
  217. package/src/packlets/spaces/spaces-service.test.ts +18 -11
  218. package/src/packlets/spaces/spaces-service.ts +123 -24
  219. package/src/packlets/storage/storage.ts +4 -4
  220. package/src/packlets/testing/invitation-utils.ts +10 -6
  221. package/src/packlets/testing/test-builder.ts +36 -10
  222. package/src/packlets/worker/worker-runtime.ts +188 -17
  223. package/src/packlets/worker/worker-session.ts +12 -18
  224. package/src/version.ts +1 -1
  225. package/dist/lib/browser/chunk-FZDVFED2.mjs.map +0 -7
  226. package/dist/lib/node-esm/chunk-JDTIU3EP.mjs.map +0 -7
  227. package/dist/types/src/packlets/identity/default-space-state-machine.d.ts +0 -19
  228. package/dist/types/src/packlets/identity/default-space-state-machine.d.ts.map +0 -1
  229. package/src/packlets/identity/default-space-state-machine.ts +0 -44
@@ -5,7 +5,9 @@
5
5
  import type { AutomergeUrl } from '@automerge/automerge-repo';
6
6
 
7
7
  import { SubscriptionList, UpdateScheduler, scheduleTask } from '@dxos/async';
8
+ import { type RequestOptions } from '@dxos/codec-protobuf';
8
9
  import { Stream } from '@dxos/codec-protobuf/stream';
10
+ import { Context } from '@dxos/context';
9
11
  import {
10
12
  type CredentialProcessor,
11
13
  createAdmissionCredentials,
@@ -13,7 +15,8 @@ import {
13
15
  getCredentialAssertion,
14
16
  } from '@dxos/credentials';
15
17
  import { raise } from '@dxos/debug';
16
- import { type SpaceManager } from '@dxos/echo-pipeline';
18
+ import { type EchoHost, type SpaceManager } from '@dxos/echo-pipeline';
19
+ import { type DatabaseDirectory } from '@dxos/echo-protocol';
17
20
  import { writeMessages } from '@dxos/feed-store';
18
21
  import { assertArgument, assertState, invariant } from '@dxos/invariant';
19
22
  import { SpaceId } from '@dxos/keys';
@@ -21,6 +24,7 @@ import { log } from '@dxos/log';
21
24
  import {
22
25
  ApiError,
23
26
  AuthorizationError,
27
+ FeedProtocol,
24
28
  IdentityNotInitializedError,
25
29
  SpaceNotFoundError,
26
30
  encodeError,
@@ -40,11 +44,13 @@ import {
40
44
  type QueryCredentialsRequest,
41
45
  type QuerySpacesResponse,
42
46
  type Space,
47
+ SpaceArchive,
43
48
  SpaceMember,
44
49
  SpaceState,
45
50
  type SpacesService,
46
51
  type SubscribeMessagesRequest,
47
52
  type UpdateMemberRoleRequest,
53
+ type CreateSpaceRequest,
48
54
  type UpdateSpaceRequest,
49
55
  type WriteCredentialsRequest,
50
56
  } from '@dxos/protocols/proto/dxos/client/services';
@@ -54,8 +60,14 @@ import { trace } from '@dxos/tracing';
54
60
  import { type Provider } from '@dxos/util';
55
61
 
56
62
  import { type IdentityManager } from '../identity';
57
- import { SpaceArchiveWriter, extractSpaceArchive } from '../space-export';
58
-
63
+ import {
64
+ SpaceArchiveWriter,
65
+ detectSpaceArchiveFormat,
66
+ extractSpaceArchive,
67
+ readSerializedSpaceArchive,
68
+ writeSerializedSpaceArchive,
69
+ objJsonToObjectStructure,
70
+ } from '../space-export';
59
71
  import { type DataSpace } from './data-space';
60
72
  import { type DataSpaceManager } from './data-space-manager';
61
73
 
@@ -63,37 +75,43 @@ export class SpacesServiceImpl implements SpacesService {
63
75
  constructor(
64
76
  private readonly _identityManager: IdentityManager,
65
77
  private readonly _spaceManager: SpaceManager,
78
+ private readonly _echoHost: EchoHost,
66
79
  private readonly _getDataSpaceManager: Provider<Promise<DataSpaceManager>>,
67
80
  ) {}
68
81
 
69
- async createSpace(): Promise<Space> {
82
+ async createSpace(request: CreateSpaceRequest, options?: RequestOptions): Promise<Space> {
70
83
  this._requireIdentity();
84
+ const ctx = options?.ctx ?? new Context();
71
85
  const dataSpaceManager = await this._getDataSpaceManager();
72
- const space = await dataSpaceManager.createSpace();
86
+ const space = await dataSpaceManager.createSpace(ctx, {
87
+ tags: request?.tags,
88
+ membershipPolicy: request?.membershipPolicy,
89
+ });
73
90
  await this._updateMetrics();
74
91
  return this._serializeSpace(space);
75
92
  }
76
93
 
77
- async updateSpace({ spaceKey, state, edgeReplication }: UpdateSpaceRequest): Promise<void> {
94
+ async updateSpace({ spaceKey, state, edgeReplication }: UpdateSpaceRequest, options?: RequestOptions): Promise<void> {
95
+ const ctx = options?.ctx ?? Context.default();
78
96
  const dataSpaceManager = await this._getDataSpaceManager();
79
97
  const space = dataSpaceManager.spaces.get(spaceKey) ?? raise(new SpaceNotFoundError(spaceKey));
80
98
 
81
99
  if (state) {
82
100
  switch (state) {
83
101
  case SpaceState.SPACE_ACTIVE:
84
- await space.activate();
102
+ await space.activate(ctx);
85
103
  break;
86
104
 
87
105
  case SpaceState.SPACE_INACTIVE:
88
- await space.deactivate();
106
+ await space.deactivate(ctx);
89
107
  break;
90
108
  default:
91
- throw new ApiError('Invalid space state');
109
+ throw new ApiError({ message: 'Invalid space state' });
92
110
  }
93
111
  }
94
112
 
95
113
  if (edgeReplication !== undefined) {
96
- await dataSpaceManager.setSpaceEdgeReplicationSetting(spaceKey, edgeReplication);
114
+ await dataSpaceManager.setSpaceEdgeReplicationSetting(ctx, spaceKey, edgeReplication);
97
115
  }
98
116
  }
99
117
 
@@ -104,9 +122,12 @@ export class SpacesServiceImpl implements SpacesService {
104
122
  throw new SpaceNotFoundError(request.spaceKey);
105
123
  }
106
124
  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),
125
+ throw new AuthorizationError({
126
+ message: 'No member management permission.',
127
+ context: {
128
+ spaceKey: space.key,
129
+ role: space.spaceState.getMemberRole(identity.identityKey),
130
+ },
110
131
  });
111
132
  }
112
133
  const credentials = await createAdmissionCredentials(
@@ -259,18 +280,26 @@ export class SpacesServiceImpl implements SpacesService {
259
280
  });
260
281
  }
261
282
 
262
- async joinBySpaceKey({ spaceKey }: JoinBySpaceKeyRequest): Promise<JoinSpaceResponse> {
283
+ async joinBySpaceKey({ spaceKey }: JoinBySpaceKeyRequest, options?: RequestOptions): Promise<JoinSpaceResponse> {
284
+ const ctx = options?.ctx ?? Context.default();
263
285
  const dataSpaceManager = await this._getDataSpaceManager();
264
- const credential = await dataSpaceManager.requestSpaceAdmissionCredential(spaceKey);
265
- return this._joinByAdmission({ credential });
286
+ const credential = await dataSpaceManager.requestSpaceAdmissionCredential(ctx, spaceKey);
287
+ return this._joinByAdmission(ctx, { credential });
266
288
  }
267
289
 
268
290
  async exportSpace(request: ExportSpaceRequest): Promise<ExportSpaceResponse> {
269
- await using writer = await new SpaceArchiveWriter().open();
270
291
  assertArgument(SpaceId.isValid(request.spaceId), 'spaceId', 'Invalid space ID');
271
292
 
272
293
  const dataSpaceManager = await this._getDataSpaceManager();
273
294
  const space = dataSpaceManager.getSpaceById(request.spaceId) ?? raise(new Error('Space not found'));
295
+
296
+ const format = request.format ?? SpaceArchive.Format.BINARY;
297
+ if (format === SpaceArchive.Format.JSON) {
298
+ const archive = await writeSerializedSpaceArchive({ space, echoHost: this._echoHost });
299
+ return { archive };
300
+ }
301
+
302
+ await using writer = await new SpaceArchiveWriter().open();
274
303
  await writer.begin({ spaceId: space.id });
275
304
  const rootUrl = space.automergeSpaceState.lastEpoch?.subject.assertion.automergeRoot;
276
305
  assertState(rootUrl, 'Space does not have a root URL');
@@ -280,15 +309,40 @@ export class SpacesServiceImpl implements SpacesService {
280
309
  await writer.writeDocument(documentId, data);
281
310
  }
282
311
 
312
+ const feeds = await space.getAllFeeds();
313
+ for (const feed of feeds) {
314
+ const archiveBlocks = feed.blocks.map((block) => ({
315
+ actorId: block.actorId,
316
+ sequence: block.sequence,
317
+ prevActorId: block.prevActorId,
318
+ prevSequence: block.prevSequence,
319
+ position: block.position,
320
+ timestamp: block.timestamp,
321
+ data: Buffer.from(block.data).toString('base64'),
322
+ }));
323
+ await writer.writeFeed(feed.feedId, feed.feedNamespace, archiveBlocks);
324
+ }
325
+
283
326
  const archive = await writer.finish();
284
327
  return { archive };
285
328
  }
286
329
 
287
- async importSpace(request: ImportSpaceRequest): Promise<ImportSpaceResponse> {
330
+ async importSpace(request: ImportSpaceRequest, options?: RequestOptions): Promise<ImportSpaceResponse> {
331
+ const ctx = options?.ctx ?? Context.default();
288
332
  const dataSpaceManager = await this._getDataSpaceManager();
333
+
334
+ const format = request.archive.format ?? detectSpaceArchiveFormat(request.archive);
335
+ if (format === SpaceArchive.Format.JSON) {
336
+ const serialized = readSerializedSpaceArchive(request.archive);
337
+ const space = await dataSpaceManager.createSpace(ctx);
338
+ await this._hydrateSpaceFromSerialized(space, serialized);
339
+ await this._updateMetrics();
340
+ return { newSpaceId: space.id };
341
+ }
342
+
289
343
  const extracted = await extractSpaceArchive(request.archive);
290
344
  invariant(extracted.metadata.echo?.currentRootUrl, 'Space archive does not contain a root URL');
291
- const space = await dataSpaceManager.createSpace({
345
+ const space = await dataSpaceManager.createSpace(ctx, {
292
346
  documents: extracted.documents,
293
347
  rootUrl: extracted.metadata.echo?.currentRootUrl as AutomergeUrl,
294
348
  });
@@ -296,7 +350,49 @@ export class SpacesServiceImpl implements SpacesService {
296
350
  return { newSpaceId: space.id };
297
351
  }
298
352
 
299
- private async _joinByAdmission({ credential }: ContactAdmission): Promise<JoinSpaceResponse> {
353
+ /**
354
+ * Populate a freshly-created space with the objects and feed messages described in a {@link SerializedSpace}.
355
+ *
356
+ * Objects are written directly into the space's automerge root document as inline
357
+ * {@link ObjectStructure} entries; feed messages are appended to the appropriate queue
358
+ * via {@link EchoHost.queuesService}.
359
+ */
360
+ private async _hydrateSpaceFromSerialized(
361
+ space: DataSpace,
362
+ serialized: ReturnType<typeof readSerializedSpaceArchive>,
363
+ ): Promise<void> {
364
+ const databaseRoot = space.databaseRoot;
365
+ assertState(databaseRoot, 'Space database root is not ready');
366
+
367
+ databaseRoot.handle.change((doc: DatabaseDirectory) => {
368
+ if (!doc.objects) {
369
+ doc.objects = {};
370
+ }
371
+ for (const obj of serialized.objects) {
372
+ doc.objects[obj.id] = objJsonToObjectStructure(obj);
373
+ }
374
+ });
375
+
376
+ for (const feed of serialized.feeds ?? []) {
377
+ if (feed.messages.length === 0) {
378
+ continue;
379
+ }
380
+ const namespace =
381
+ feed.namespace === 'trace' ? FeedProtocol.WellKnownNamespaces.trace : FeedProtocol.WellKnownNamespaces.data;
382
+ try {
383
+ await this._echoHost.queuesService.insertIntoQueue({
384
+ spaceId: space.id,
385
+ queueId: feed.feedObjectId,
386
+ subspaceTag: namespace,
387
+ objects: feed.messages.map((message) => JSON.stringify(message)),
388
+ });
389
+ } catch (err) {
390
+ log.warn('failed to import feed data', { feedObjectId: feed.feedObjectId, error: err });
391
+ }
392
+ }
393
+ }
394
+
395
+ private async _joinByAdmission(ctx: Context, { credential }: ContactAdmission): Promise<JoinSpaceResponse> {
300
396
  const assertion = getCredentialAssertion(credential);
301
397
  invariant(assertion['@type'] === 'dxos.halo.credentials.SpaceMember', 'Invalid credential');
302
398
  const myIdentity = this._identityManager.identity;
@@ -305,9 +401,10 @@ export class SpacesServiceImpl implements SpacesService {
305
401
  const dataSpaceManager = await this._getDataSpaceManager();
306
402
  let dataSpace = dataSpaceManager.spaces.get(assertion.spaceKey);
307
403
  if (!dataSpace) {
308
- dataSpace = await dataSpaceManager.acceptSpace({
404
+ dataSpace = await dataSpaceManager.acceptSpace(ctx, {
309
405
  spaceKey: assertion.spaceKey,
310
406
  genesisFeedKey: assertion.genesisFeedKey,
407
+ tags: assertion.tags,
311
408
  });
312
409
  await myIdentity.controlPipeline.writer.write({ credential: { credential } });
313
410
  }
@@ -360,6 +457,8 @@ export class SpacesServiceImpl implements SpacesService {
360
457
  }),
361
458
  ),
362
459
  creator: space.inner.spaceState.creator?.key,
460
+ tags: space.tags,
461
+ membershipPolicy: space.membershipPolicy,
363
462
  cache: space.cache,
364
463
  metrics: space.metrics,
365
464
  edgeReplication: space.getEdgeReplicationSetting(),
@@ -368,9 +467,9 @@ export class SpacesServiceImpl implements SpacesService {
368
467
 
369
468
  private _requireIdentity() {
370
469
  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
- );
470
+ throw new IdentityNotInitializedError({
471
+ message: 'This device has no HALO identity available. See https://docs.dxos.org/guide/platform/halo',
472
+ });
374
473
  }
375
474
  return this._identityManager.identity;
376
475
  }
@@ -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 {
@@ -4,6 +4,7 @@
4
4
 
5
5
  import { Trigger } from '@dxos/async';
6
6
  import { type AuthenticatingInvitation, type CancellableInvitation, InvitationEncoder } from '@dxos/client-protocol';
7
+ import { Context } from '@dxos/context';
7
8
  import { invariant } from '@dxos/invariant';
8
9
  import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
9
10
  import { type DeviceProfileDocument } from '@dxos/protocols/proto/dxos/halo/credentials';
@@ -36,15 +37,15 @@ export type PerformInvitationCallbacks<T> = {
36
37
  onError?: (value: T) => boolean | void;
37
38
  };
38
39
 
39
- export type PerformInvitationParams = {
40
+ export type PerformInvitationProps = {
40
41
  host: ServiceContext | InvitationHost;
41
42
  guest: ServiceContext | InvitationGuest;
43
+ guestDeviceProfile?: DeviceProfileDocument;
42
44
  options?: Partial<Invitation>;
43
45
  hooks?: {
44
46
  host?: PerformInvitationCallbacks<CancellableInvitation>;
45
47
  guest?: PerformInvitationCallbacks<AuthenticatingInvitation>;
46
48
  };
47
- guestDeviceProfile?: DeviceProfileDocument;
48
49
  codeInputDelay?: number;
49
50
  };
50
51
 
@@ -52,14 +53,17 @@ export type Result = { invitation?: Invitation; error?: Error };
52
53
 
53
54
  // TODO(burdon): Make async.
54
55
  // TODO(burdon): Rename startInvitation.
56
+ /**
57
+ *
58
+ */
55
59
  export const performInvitation = ({
56
60
  host,
57
61
  guest,
62
+ guestDeviceProfile,
58
63
  options,
59
64
  hooks,
60
- guestDeviceProfile,
61
65
  codeInputDelay,
62
- }: PerformInvitationParams): [Promise<Result>, Promise<Result>] => {
66
+ }: PerformInvitationProps): [Promise<Result>, Promise<Result>] => {
63
67
  let guestError = false;
64
68
  let guestConnected = false;
65
69
  let wereConnected = false;
@@ -226,7 +230,7 @@ export const createInvitation = async (
226
230
  };
227
231
 
228
232
  if (host instanceof ServiceContext) {
229
- return host.invitationsManager.createInvitation({
233
+ return host.invitationsManager.createInvitation(new Context(), {
230
234
  kind: Invitation.Kind.SPACE,
231
235
  ...options,
232
236
  });
@@ -243,7 +247,7 @@ export const acceptInvitation = (
243
247
  invitation = sanitizeInvitation(invitation);
244
248
 
245
249
  if (guest instanceof ServiceContext) {
246
- return guest.invitationsManager.acceptInvitation({
250
+ return guest.invitationsManager.acceptInvitation(new Context(), {
247
251
  invitation,
248
252
  deviceProfile: guestDeviceProfile,
249
253
  });
@@ -2,6 +2,10 @@
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
11
  import { CredentialGenerator, createCredentialSignerWithChain } from '@dxos/credentials';
@@ -15,11 +19,13 @@ import { MemorySignalManager, MemorySignalManagerContext, type SignalManager } f
15
19
  import { MemoryTransportFactory, SwarmNetworkManager } from '@dxos/network-manager';
16
20
  import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
17
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