@dxos/client-services 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (304) hide show
  1. package/dist/lib/chunk-client-services-layer.mjs +11425 -0
  2. package/dist/lib/chunk-client-services-layer.mjs.map +1 -0
  3. package/dist/lib/chunk-decorate.mjs +9 -0
  4. package/dist/lib/index.mjs +731 -0
  5. package/dist/lib/index.mjs.map +1 -0
  6. package/dist/lib/packlets/diagnostics/browser-diagnostics-broadcast.mjs +72 -0
  7. package/dist/lib/packlets/diagnostics/browser-diagnostics-broadcast.mjs.map +1 -0
  8. package/dist/lib/packlets/diagnostics/diagnostics-broadcast.mjs +14 -0
  9. package/dist/lib/packlets/diagnostics/diagnostics-broadcast.mjs.map +1 -0
  10. package/dist/lib/packlets/locks/browser.mjs +105 -0
  11. package/dist/lib/packlets/locks/browser.mjs.map +1 -0
  12. package/dist/lib/packlets/locks/node.mjs +53 -0
  13. package/dist/lib/packlets/locks/node.mjs.map +1 -0
  14. package/dist/lib/testing.mjs +570 -0
  15. package/dist/lib/testing.mjs.map +1 -0
  16. package/dist/types/src/index.d.ts +2 -0
  17. package/dist/types/src/index.d.ts.map +1 -1
  18. package/dist/types/src/packlets/agents/edge-agent-manager.d.ts +21 -4
  19. package/dist/types/src/packlets/agents/edge-agent-manager.d.ts.map +1 -1
  20. package/dist/types/src/packlets/agents/edge-agent-service.d.ts +8 -7
  21. package/dist/types/src/packlets/agents/edge-agent-service.d.ts.map +1 -1
  22. package/dist/types/src/packlets/devices/devices-service.d.ts +7 -5
  23. package/dist/types/src/packlets/devices/devices-service.d.ts.map +1 -1
  24. package/dist/types/src/packlets/devtools/devtools.d.ts +30 -29
  25. package/dist/types/src/packlets/devtools/devtools.d.ts.map +1 -1
  26. package/dist/types/src/packlets/devtools/feeds.d.ts +1 -1
  27. package/dist/types/src/packlets/devtools/feeds.d.ts.map +1 -1
  28. package/dist/types/src/packlets/devtools/network.d.ts +2 -1
  29. package/dist/types/src/packlets/devtools/network.d.ts.map +1 -1
  30. package/dist/types/src/packlets/devtools/spaces.d.ts.map +1 -1
  31. package/dist/types/src/packlets/diagnostics/diagnostics-broadcast.d.ts +2 -2
  32. package/dist/types/src/packlets/diagnostics/diagnostics-broadcast.d.ts.map +1 -1
  33. package/dist/types/src/packlets/diagnostics/diagnostics-collector.d.ts.map +1 -1
  34. package/dist/types/src/packlets/diagnostics/diagnostics.d.ts +1 -8
  35. package/dist/types/src/packlets/diagnostics/diagnostics.d.ts.map +1 -1
  36. package/dist/types/src/packlets/identity/authenticator.d.ts +1 -1
  37. package/dist/types/src/packlets/identity/authenticator.d.ts.map +1 -1
  38. package/dist/types/src/packlets/identity/contacts-service.d.ts +9 -6
  39. package/dist/types/src/packlets/identity/contacts-service.d.ts.map +1 -1
  40. package/dist/types/src/packlets/identity/identity-manager.d.ts +32 -3
  41. package/dist/types/src/packlets/identity/identity-manager.d.ts.map +1 -1
  42. package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts +23 -4
  43. package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts.map +1 -1
  44. package/dist/types/src/packlets/identity/identity-service.d.ts +15 -20
  45. package/dist/types/src/packlets/identity/identity-service.d.ts.map +1 -1
  46. package/dist/types/src/packlets/identity/identity.d.ts +2 -2
  47. package/dist/types/src/packlets/identity/identity.d.ts.map +1 -1
  48. package/dist/types/src/packlets/invitations/edge-invitation-handler.d.ts.map +1 -1
  49. package/dist/types/src/packlets/invitations/invitations-handler.d.ts +17 -0
  50. package/dist/types/src/packlets/invitations/invitations-handler.d.ts.map +1 -1
  51. package/dist/types/src/packlets/invitations/invitations-manager.d.ts +25 -4
  52. package/dist/types/src/packlets/invitations/invitations-manager.d.ts.map +1 -1
  53. package/dist/types/src/packlets/invitations/invitations-service.d.ts +11 -11
  54. package/dist/types/src/packlets/invitations/invitations-service.d.ts.map +1 -1
  55. package/dist/types/src/packlets/logging/logging-service.d.ts +14 -12
  56. package/dist/types/src/packlets/logging/logging-service.d.ts.map +1 -1
  57. package/dist/types/src/packlets/metadata/index.d.ts +3 -0
  58. package/dist/types/src/packlets/metadata/index.d.ts.map +1 -0
  59. package/dist/types/src/packlets/metadata/metadata-store.d.ts +107 -0
  60. package/dist/types/src/packlets/metadata/metadata-store.d.ts.map +1 -0
  61. package/dist/types/src/packlets/metadata/metadata-store.test.d.ts +2 -0
  62. package/dist/types/src/packlets/metadata/metadata-store.test.d.ts.map +1 -0
  63. package/dist/types/src/packlets/metadata/sqlite-metadata-store.d.ts +65 -0
  64. package/dist/types/src/packlets/metadata/sqlite-metadata-store.d.ts.map +1 -0
  65. package/dist/types/src/packlets/network/network-service.d.ts +15 -14
  66. package/dist/types/src/packlets/network/network-service.d.ts.map +1 -1
  67. package/dist/types/src/packlets/pipeline/codec.d.ts +11 -0
  68. package/dist/types/src/packlets/pipeline/codec.d.ts.map +1 -0
  69. package/dist/types/src/packlets/pipeline/feeds.d.ts +7 -0
  70. package/dist/types/src/packlets/pipeline/feeds.d.ts.map +1 -0
  71. package/dist/types/src/packlets/pipeline/index.d.ts +5 -0
  72. package/dist/types/src/packlets/pipeline/index.d.ts.map +1 -0
  73. package/dist/types/src/packlets/pipeline/message-selector.d.ts +11 -0
  74. package/dist/types/src/packlets/pipeline/message-selector.d.ts.map +1 -0
  75. package/dist/types/src/packlets/pipeline/pipeline-stress.test.d.ts +2 -0
  76. package/dist/types/src/packlets/pipeline/pipeline-stress.test.d.ts.map +1 -0
  77. package/dist/types/src/packlets/pipeline/pipeline.d.ts +131 -0
  78. package/dist/types/src/packlets/pipeline/pipeline.d.ts.map +1 -0
  79. package/dist/types/src/packlets/pipeline/pipeline.test.d.ts +2 -0
  80. package/dist/types/src/packlets/pipeline/pipeline.test.d.ts.map +1 -0
  81. package/dist/types/src/packlets/pipeline/testing/index.d.ts +2 -0
  82. package/dist/types/src/packlets/pipeline/testing/index.d.ts.map +1 -0
  83. package/dist/types/src/packlets/pipeline/testing/test-feed-builder.d.ts +9 -0
  84. package/dist/types/src/packlets/pipeline/testing/test-feed-builder.d.ts.map +1 -0
  85. package/dist/types/src/packlets/pipeline/timeframe-clock.d.ts +31 -0
  86. package/dist/types/src/packlets/pipeline/timeframe-clock.d.ts.map +1 -0
  87. package/dist/types/src/packlets/services/client-services-layer.d.ts +21 -0
  88. package/dist/types/src/packlets/services/client-services-layer.d.ts.map +1 -0
  89. package/dist/types/src/packlets/services/cross-device-space-synchronizer.d.ts +28 -0
  90. package/dist/types/src/packlets/services/cross-device-space-synchronizer.d.ts.map +1 -0
  91. package/dist/types/src/packlets/services/effect-rpc.test.d.ts +2 -0
  92. package/dist/types/src/packlets/services/effect-rpc.test.d.ts.map +1 -0
  93. package/dist/types/src/packlets/services/feed-syncer.d.ts +22 -2
  94. package/dist/types/src/packlets/services/feed-syncer.d.ts.map +1 -1
  95. package/dist/types/src/packlets/services/index.d.ts +2 -2
  96. package/dist/types/src/packlets/services/index.d.ts.map +1 -1
  97. package/dist/types/src/packlets/services/platform.d.ts.map +1 -1
  98. package/dist/types/src/packlets/services/service-context.d.ts +38 -57
  99. package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
  100. package/dist/types/src/packlets/services/service-host.d.ts +82 -31
  101. package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
  102. package/dist/types/src/packlets/services/sqlite-storage.d.ts +29 -0
  103. package/dist/types/src/packlets/services/sqlite-storage.d.ts.map +1 -1
  104. package/dist/types/src/packlets/services/sqlite-storage.test.d.ts +2 -0
  105. package/dist/types/src/packlets/services/sqlite-storage.test.d.ts.map +1 -0
  106. package/dist/types/src/packlets/space/admission-discovery-extension.d.ts +30 -0
  107. package/dist/types/src/packlets/space/admission-discovery-extension.d.ts.map +1 -0
  108. package/dist/types/src/packlets/space/auth.d.ts +24 -0
  109. package/dist/types/src/packlets/space/auth.d.ts.map +1 -0
  110. package/dist/types/src/packlets/space/control-pipeline.d.ts +46 -0
  111. package/dist/types/src/packlets/space/control-pipeline.d.ts.map +1 -0
  112. package/dist/types/src/packlets/space/control-pipeline.test.d.ts +2 -0
  113. package/dist/types/src/packlets/space/control-pipeline.test.d.ts.map +1 -0
  114. package/dist/types/src/packlets/space/index.d.ts +6 -0
  115. package/dist/types/src/packlets/space/index.d.ts.map +1 -0
  116. package/dist/types/src/packlets/space/replication.browser.test.d.ts +2 -0
  117. package/dist/types/src/packlets/space/replication.browser.test.d.ts.map +1 -0
  118. package/dist/types/src/packlets/space/space-manager.browser.test.d.ts +2 -0
  119. package/dist/types/src/packlets/space/space-manager.browser.test.d.ts.map +1 -0
  120. package/dist/types/src/packlets/space/space-manager.d.ts +72 -0
  121. package/dist/types/src/packlets/space/space-manager.d.ts.map +1 -0
  122. package/dist/types/src/packlets/space/space-protocol.browser.test.d.ts +2 -0
  123. package/dist/types/src/packlets/space/space-protocol.browser.test.d.ts.map +1 -0
  124. package/dist/types/src/packlets/space/space-protocol.d.ts +99 -0
  125. package/dist/types/src/packlets/space/space-protocol.d.ts.map +1 -0
  126. package/dist/types/src/packlets/space/space-protocol.test.d.ts +2 -0
  127. package/dist/types/src/packlets/space/space-protocol.test.d.ts.map +1 -0
  128. package/dist/types/src/packlets/space/space.d.ts +65 -0
  129. package/dist/types/src/packlets/space/space.d.ts.map +1 -0
  130. package/dist/types/src/packlets/space/space.test.d.ts +2 -0
  131. package/dist/types/src/packlets/space/space.test.d.ts.map +1 -0
  132. package/dist/types/src/packlets/space/testing/change-metadata.d.ts +8 -0
  133. package/dist/types/src/packlets/space/testing/change-metadata.d.ts.map +1 -0
  134. package/dist/types/src/packlets/space/testing/index.d.ts +4 -0
  135. package/dist/types/src/packlets/space/testing/index.d.ts.map +1 -0
  136. package/dist/types/src/packlets/space/testing/test-agent-builder.d.ts +62 -0
  137. package/dist/types/src/packlets/space/testing/test-agent-builder.d.ts.map +1 -0
  138. package/dist/types/src/packlets/space-export/serialized-space-reader.d.ts +1 -1
  139. package/dist/types/src/packlets/space-export/serialized-space-reader.d.ts.map +1 -1
  140. package/dist/types/src/packlets/space-export/serialized-space-writer.d.ts.map +1 -1
  141. package/dist/types/src/packlets/spaces/data-space-manager.d.ts +40 -7
  142. package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
  143. package/dist/types/src/packlets/spaces/data-space.d.ts +3 -1
  144. package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
  145. package/dist/types/src/packlets/spaces/genesis.d.ts +1 -1
  146. package/dist/types/src/packlets/spaces/genesis.d.ts.map +1 -1
  147. package/dist/types/src/packlets/spaces/spaces-service.d.ts +25 -23
  148. package/dist/types/src/packlets/spaces/spaces-service.d.ts.map +1 -1
  149. package/dist/types/src/packlets/storage/level.d.ts.map +1 -1
  150. package/dist/types/src/packlets/system/system-service.d.ts +18 -18
  151. package/dist/types/src/packlets/system/system-service.d.ts.map +1 -1
  152. package/dist/types/src/packlets/testing/invitation-utils.d.ts +1 -1
  153. package/dist/types/src/packlets/testing/invitation-utils.d.ts.map +1 -1
  154. package/dist/types/src/packlets/testing/test-builder.d.ts +7 -6
  155. package/dist/types/src/packlets/testing/test-builder.d.ts.map +1 -1
  156. package/dist/types/src/packlets/worker/worker-runtime.d.ts +41 -58
  157. package/dist/types/src/packlets/worker/worker-runtime.d.ts.map +1 -1
  158. package/dist/types/src/packlets/worker/worker-session.d.ts +21 -8
  159. package/dist/types/src/packlets/worker/worker-session.d.ts.map +1 -1
  160. package/dist/types/src/testing/index.d.ts +1 -0
  161. package/dist/types/src/testing/index.d.ts.map +1 -1
  162. package/dist/types/src/version.d.ts +1 -1
  163. package/dist/types/tsconfig.tsbuildinfo +1 -1
  164. package/package.json +52 -48
  165. package/src/index.ts +2 -0
  166. package/src/packlets/agents/edge-agent-manager.ts +56 -15
  167. package/src/packlets/agents/edge-agent-service.ts +25 -15
  168. package/src/packlets/devices/devices-service.test.ts +20 -19
  169. package/src/packlets/devices/devices-service.ts +17 -17
  170. package/src/packlets/devtools/devtools.ts +133 -75
  171. package/src/packlets/devtools/feeds.ts +2 -1
  172. package/src/packlets/devtools/network.ts +42 -12
  173. package/src/packlets/devtools/spaces.ts +1 -1
  174. package/src/packlets/diagnostics/diagnostics-broadcast.ts +4 -2
  175. package/src/packlets/diagnostics/diagnostics-collector.ts +5 -18
  176. package/src/packlets/diagnostics/diagnostics.ts +0 -11
  177. package/src/packlets/identity/authenticator.ts +2 -1
  178. package/src/packlets/identity/contacts-service.ts +46 -37
  179. package/src/packlets/identity/identity-manager.test.ts +3 -1
  180. package/src/packlets/identity/identity-manager.ts +73 -5
  181. package/src/packlets/identity/identity-recovery-manager.ts +56 -7
  182. package/src/packlets/identity/identity-service.test.ts +27 -18
  183. package/src/packlets/identity/identity-service.ts +114 -71
  184. package/src/packlets/identity/identity.test.ts +4 -9
  185. package/src/packlets/identity/identity.ts +1 -2
  186. package/src/packlets/invitations/edge-invitation-handler.ts +0 -1
  187. package/src/packlets/invitations/invitations-handler.ts +39 -3
  188. package/src/packlets/invitations/invitations-manager.ts +52 -4
  189. package/src/packlets/invitations/invitations-service.ts +54 -28
  190. package/src/packlets/logging/logging-service.ts +41 -29
  191. package/src/packlets/logging/logging.test.ts +28 -15
  192. package/src/packlets/metadata/index.ts +6 -0
  193. package/src/packlets/metadata/metadata-store.test.ts +49 -0
  194. package/src/packlets/metadata/metadata-store.ts +446 -0
  195. package/src/packlets/metadata/sqlite-metadata-store.ts +409 -0
  196. package/src/packlets/network/network-service.test.ts +19 -12
  197. package/src/packlets/network/network-service.ts +96 -29
  198. package/src/packlets/pipeline/codec.ts +18 -0
  199. package/src/packlets/pipeline/feeds.ts +22 -0
  200. package/src/packlets/pipeline/index.ts +8 -0
  201. package/src/packlets/pipeline/message-selector.ts +35 -0
  202. package/src/packlets/pipeline/pipeline-stress.test.ts +230 -0
  203. package/src/packlets/pipeline/pipeline.test.ts +140 -0
  204. package/src/packlets/pipeline/pipeline.ts +439 -0
  205. package/src/packlets/pipeline/testing/index.ts +5 -0
  206. package/src/packlets/pipeline/testing/test-feed-builder.ts +19 -0
  207. package/src/packlets/pipeline/timeframe-clock.ts +81 -0
  208. package/src/packlets/services/client-services-layer.ts +186 -0
  209. package/src/packlets/services/cross-device-space-synchronizer.ts +132 -0
  210. package/src/packlets/services/effect-rpc.test.ts +314 -0
  211. package/src/packlets/services/feed-syncer.ts +57 -3
  212. package/src/packlets/services/index.ts +2 -2
  213. package/src/packlets/services/platform.ts +0 -6
  214. package/src/packlets/services/service-context.ts +219 -522
  215. package/src/packlets/services/service-host.test.ts +34 -11
  216. package/src/packlets/services/service-host.ts +693 -213
  217. package/src/packlets/services/spec.md +106 -0
  218. package/src/packlets/services/sqlite-storage.test.ts +48 -0
  219. package/src/packlets/services/sqlite-storage.ts +117 -20
  220. package/src/packlets/space/admission-discovery-extension.ts +91 -0
  221. package/src/packlets/space/auth.ts +92 -0
  222. package/src/packlets/space/control-pipeline.test.ts +165 -0
  223. package/src/packlets/space/control-pipeline.ts +229 -0
  224. package/src/packlets/space/index.ts +9 -0
  225. package/src/packlets/space/replication.browser.test.ts +58 -0
  226. package/src/packlets/space/space-manager.browser.test.ts +40 -0
  227. package/src/packlets/space/space-manager.ts +224 -0
  228. package/src/packlets/space/space-protocol.browser.test.ts +129 -0
  229. package/src/packlets/space/space-protocol.test.ts +158 -0
  230. package/src/packlets/space/space-protocol.ts +308 -0
  231. package/src/packlets/space/space.test.ts +181 -0
  232. package/src/packlets/space/space.ts +196 -0
  233. package/src/packlets/space/testing/change-metadata.ts +27 -0
  234. package/src/packlets/space/testing/index.ts +7 -0
  235. package/src/packlets/space/testing/test-agent-builder.ts +252 -0
  236. package/src/packlets/space-export/serialized-space-reader.ts +3 -1
  237. package/src/packlets/space-export/serialized-space-writer.ts +53 -30
  238. package/src/packlets/space-export/space-archive.test.ts +30 -0
  239. package/src/packlets/spaces/data-space-manager.test.ts +1 -1
  240. package/src/packlets/spaces/data-space-manager.ts +148 -33
  241. package/src/packlets/spaces/data-space.ts +29 -18
  242. package/src/packlets/spaces/edge-feed-replicator.test.ts +1 -1
  243. package/src/packlets/spaces/genesis.ts +1 -1
  244. package/src/packlets/spaces/spaces-service.test.ts +35 -22
  245. package/src/packlets/spaces/spaces-service.ts +259 -180
  246. package/src/packlets/storage/level.ts +3 -1
  247. package/src/packlets/system/system-service.test.ts +31 -13
  248. package/src/packlets/system/system-service.ts +65 -37
  249. package/src/packlets/testing/invitation-utils.ts +3 -3
  250. package/src/packlets/testing/test-builder.ts +35 -20
  251. package/src/packlets/worker/worker-runtime.ts +222 -260
  252. package/src/packlets/worker/worker-session.ts +108 -91
  253. package/src/testing/index.ts +1 -0
  254. package/src/version.ts +1 -1
  255. package/dist/lib/browser/chunk-QCWEHHJW.mjs +0 -24
  256. package/dist/lib/browser/chunk-QCWEHHJW.mjs.map +0 -7
  257. package/dist/lib/browser/chunk-XJRPB3GA.mjs +0 -22
  258. package/dist/lib/browser/chunk-XJRPB3GA.mjs.map +0 -7
  259. package/dist/lib/browser/chunk-XU5R2BMF.mjs +0 -8837
  260. package/dist/lib/browser/chunk-XU5R2BMF.mjs.map +0 -7
  261. package/dist/lib/browser/index.mjs +0 -876
  262. package/dist/lib/browser/index.mjs.map +0 -7
  263. package/dist/lib/browser/meta.json +0 -1
  264. package/dist/lib/browser/packlets/diagnostics/browser-diagnostics-broadcast.mjs +0 -88
  265. package/dist/lib/browser/packlets/diagnostics/browser-diagnostics-broadcast.mjs.map +0 -7
  266. package/dist/lib/browser/packlets/diagnostics/diagnostics-broadcast.mjs +0 -11
  267. package/dist/lib/browser/packlets/diagnostics/diagnostics-broadcast.mjs.map +0 -7
  268. package/dist/lib/browser/packlets/locks/browser.mjs +0 -86
  269. package/dist/lib/browser/packlets/locks/browser.mjs.map +0 -7
  270. package/dist/lib/browser/packlets/locks/node.mjs +0 -48
  271. package/dist/lib/browser/packlets/locks/node.mjs.map +0 -7
  272. package/dist/lib/browser/testing/index.mjs +0 -436
  273. package/dist/lib/browser/testing/index.mjs.map +0 -7
  274. package/dist/lib/node-esm/chunk-2DT3MZRL.mjs +0 -22
  275. package/dist/lib/node-esm/chunk-2DT3MZRL.mjs.map +0 -7
  276. package/dist/lib/node-esm/chunk-2SZHAWBN.mjs +0 -24
  277. package/dist/lib/node-esm/chunk-2SZHAWBN.mjs.map +0 -7
  278. package/dist/lib/node-esm/chunk-H5YTUD35.mjs +0 -8837
  279. package/dist/lib/node-esm/chunk-H5YTUD35.mjs.map +0 -7
  280. package/dist/lib/node-esm/index.mjs +0 -876
  281. package/dist/lib/node-esm/index.mjs.map +0 -7
  282. package/dist/lib/node-esm/meta.json +0 -1
  283. package/dist/lib/node-esm/packlets/diagnostics/browser-diagnostics-broadcast.mjs +0 -88
  284. package/dist/lib/node-esm/packlets/diagnostics/browser-diagnostics-broadcast.mjs.map +0 -7
  285. package/dist/lib/node-esm/packlets/diagnostics/diagnostics-broadcast.mjs +0 -11
  286. package/dist/lib/node-esm/packlets/diagnostics/diagnostics-broadcast.mjs.map +0 -7
  287. package/dist/lib/node-esm/packlets/locks/browser.mjs +0 -86
  288. package/dist/lib/node-esm/packlets/locks/browser.mjs.map +0 -7
  289. package/dist/lib/node-esm/packlets/locks/node.mjs +0 -48
  290. package/dist/lib/node-esm/packlets/locks/node.mjs.map +0 -7
  291. package/dist/lib/node-esm/testing/index.mjs +0 -436
  292. package/dist/lib/node-esm/testing/index.mjs.map +0 -7
  293. package/dist/types/src/packlets/services/client-rpc-server.d.ts +0 -24
  294. package/dist/types/src/packlets/services/client-rpc-server.d.ts.map +0 -1
  295. package/dist/types/src/packlets/services/service-registry.d.ts +0 -15
  296. package/dist/types/src/packlets/services/service-registry.d.ts.map +0 -1
  297. package/dist/types/src/packlets/services/service-registry.test.d.ts +0 -2
  298. package/dist/types/src/packlets/services/service-registry.test.d.ts.map +0 -1
  299. package/dist/types/src/testing/setup.d.ts +0 -3
  300. package/dist/types/src/testing/setup.d.ts.map +0 -1
  301. package/src/packlets/services/client-rpc-server.ts +0 -111
  302. package/src/packlets/services/service-registry.test.ts +0 -78
  303. package/src/packlets/services/service-registry.ts +0 -36
  304. package/src/testing/setup.ts +0 -11
@@ -3,10 +3,10 @@
3
3
  //
4
4
 
5
5
  import type { AutomergeUrl } from '@automerge/automerge-repo';
6
+ import * as Effect from 'effect/Effect';
7
+ import * as EffectStream from 'effect/Stream';
6
8
 
7
9
  import { SubscriptionList, UpdateScheduler, scheduleTask } from '@dxos/async';
8
- import { type RequestOptions } from '@dxos/codec-protobuf';
9
- import { Stream } from '@dxos/codec-protobuf/stream';
10
10
  import { Context } from '@dxos/context';
11
11
  import {
12
12
  type CredentialProcessor,
@@ -15,8 +15,9 @@ import {
15
15
  getCredentialAssertion,
16
16
  } from '@dxos/credentials';
17
17
  import { raise } from '@dxos/debug';
18
- import { type EchoHost, type SpaceManager } from '@dxos/echo-host';
18
+ import { type EchoHost } from '@dxos/echo-host';
19
19
  import { type DatabaseDirectory } from '@dxos/echo-protocol';
20
+ import { EffectEx } from '@dxos/effect';
20
21
  import { writeMessages } from '@dxos/feed-store';
21
22
  import { assertArgument, assertState, invariant } from '@dxos/invariant';
22
23
  import { SpaceId } from '@dxos/keys';
@@ -28,6 +29,7 @@ import {
28
29
  IdentityNotInitializedError,
29
30
  SpaceNotFoundError,
30
31
  encodeError,
32
+ makeInProcessClient,
31
33
  } from '@dxos/protocols';
32
34
  import {
33
35
  type AdmitContactRequest,
@@ -47,7 +49,6 @@ import {
47
49
  type Space,
48
50
  SpaceArchive,
49
51
  SpaceMember,
50
- type SpacesService,
51
52
  SpaceState,
52
53
  type SubscribeMessagesRequest,
53
54
  type UpdateMemberRoleRequest,
@@ -56,10 +57,12 @@ import {
56
57
  } from '@dxos/protocols/proto/dxos/client/services';
57
58
  import { type Credential } from '@dxos/protocols/proto/dxos/halo/credentials';
58
59
  import { type GossipMessage } from '@dxos/protocols/proto/dxos/mesh/teleport/gossip';
60
+ import { FeedService, type SpacesService } from '@dxos/protocols/rpc';
59
61
  import { trace } from '@dxos/tracing';
60
62
  import { type Provider } from '@dxos/util';
61
63
 
62
64
  import { type IdentityManager } from '../identity';
65
+ import { type SpaceManager } from '../space';
63
66
  import {
64
67
  SpaceArchiveWriter,
65
68
  detectSpaceArchiveFormat,
@@ -71,86 +74,102 @@ import {
71
74
  import { type DataSpace } from './data-space';
72
75
  import { type DataSpaceManager } from './data-space-manager';
73
76
 
74
- export class SpacesServiceImpl implements SpacesService {
75
- constructor(
77
+ export class SpacesServiceImpl implements SpacesService.Handlers {
78
+ 'constructor'(
76
79
  private readonly _identityManager: IdentityManager,
77
80
  private readonly _spaceManager: SpaceManager,
78
81
  private readonly _echoHost: EchoHost,
79
82
  private readonly _getDataSpaceManager: Provider<Promise<DataSpaceManager>>,
80
83
  ) {}
81
84
 
82
- async createSpace(request: CreateSpaceRequest, options?: RequestOptions): Promise<Space> {
83
- this._requireIdentity();
84
- const ctx = options?.ctx ?? new Context();
85
- const dataSpaceManager = await this._getDataSpaceManager();
86
- const space = await dataSpaceManager.createSpace(ctx, {
87
- tags: request?.tags,
88
- membershipPolicy: request?.membershipPolicy,
85
+ ['SpacesService.createSpace'](request: CreateSpaceRequest): Effect.Effect<Space, Error> {
86
+ return Effect.tryPromise({
87
+ try: async () => {
88
+ this._requireIdentity();
89
+ const ctx = new Context();
90
+ const dataSpaceManager = await this._getDataSpaceManager();
91
+ const space = await dataSpaceManager.createSpace(ctx, {
92
+ tags: request?.tags,
93
+ membershipPolicy: request?.membershipPolicy,
94
+ });
95
+ await this._updateMetrics();
96
+ return this._serializeSpace(space);
97
+ },
98
+ catch: (error) => error as Error,
89
99
  });
90
- await this._updateMetrics();
91
- return this._serializeSpace(space);
92
100
  }
93
101
 
94
- async updateSpace({ spaceKey, state, edgeReplication }: UpdateSpaceRequest, options?: RequestOptions): Promise<void> {
95
- const ctx = options?.ctx ?? Context.default();
96
- const dataSpaceManager = await this._getDataSpaceManager();
97
- const space = dataSpaceManager.spaces.get(spaceKey) ?? raise(new SpaceNotFoundError(spaceKey));
98
-
99
- if (state) {
100
- switch (state) {
101
- case SpaceState.SPACE_ACTIVE:
102
- await space.activate(ctx);
103
- break;
104
-
105
- case SpaceState.SPACE_INACTIVE:
106
- await space.deactivate(ctx);
107
- break;
108
-
109
- case SpaceState.SPACE_DELETED:
110
- await dataSpaceManager.markSpaceDeleted(ctx, spaceKey);
111
- // The space is removed from the manager; skip any further mutations (e.g. edgeReplication).
112
- return;
113
- default:
114
- throw new ApiError({ message: 'Invalid space state' });
115
- }
116
- }
102
+ ['SpacesService.updateSpace']({ spaceKey, state, edgeReplication }: UpdateSpaceRequest): Effect.Effect<void, Error> {
103
+ return Effect.tryPromise({
104
+ try: async () => {
105
+ const ctx = Context.default();
106
+ const dataSpaceManager = await this._getDataSpaceManager();
107
+ const space = dataSpaceManager.spaces.get(spaceKey) ?? raise(new SpaceNotFoundError(spaceKey));
117
108
 
118
- if (edgeReplication !== undefined) {
119
- await dataSpaceManager.setSpaceEdgeReplicationSetting(ctx, spaceKey, edgeReplication);
120
- }
109
+ if (state) {
110
+ switch (state) {
111
+ case SpaceState.SPACE_ACTIVE:
112
+ await space.activate(ctx);
113
+ break;
114
+
115
+ case SpaceState.SPACE_INACTIVE:
116
+ await space.deactivate(ctx);
117
+ break;
118
+
119
+ case SpaceState.SPACE_DELETED:
120
+ await dataSpaceManager.markSpaceDeleted(ctx, spaceKey);
121
+ // The space is removed from the manager; skip any further mutations (e.g. edgeReplication).
122
+ return;
123
+ default:
124
+ throw new ApiError({ message: 'Invalid space state' });
125
+ }
126
+ }
127
+
128
+ if (edgeReplication !== undefined) {
129
+ await dataSpaceManager.setSpaceEdgeReplicationSetting(ctx, spaceKey, edgeReplication);
130
+ }
131
+ },
132
+ catch: (error) => error as Error,
133
+ });
121
134
  }
122
135
 
123
- async updateMemberRole(request: UpdateMemberRoleRequest): Promise<void> {
124
- const identity = this._requireIdentity();
125
- const space = this._spaceManager.spaces.get(request.spaceKey);
126
- if (space == null) {
127
- throw new SpaceNotFoundError(request.spaceKey);
128
- }
129
- if (!space.spaceState.hasMembershipManagementPermission(identity.identityKey)) {
130
- throw new AuthorizationError({
131
- message: 'No member management permission.',
132
- context: {
133
- spaceKey: space.key,
134
- role: space.spaceState.getMemberRole(identity.identityKey),
135
- },
136
- });
137
- }
138
- const credentials = await createAdmissionCredentials(
139
- identity.getIdentityCredentialSigner(),
140
- request.memberKey,
141
- space.key,
142
- space.genesisFeedKey,
143
- request.newRole,
144
- space.spaceState.membershipChainHeads,
145
- );
146
- invariant(credentials[0].credential);
147
- const spaceMemberCredential = credentials[0].credential.credential;
148
- invariant(getCredentialAssertion(spaceMemberCredential)['@type'] === 'dxos.halo.credentials.SpaceMember');
149
- await writeMessages(space.controlPipeline.writer, credentials);
136
+ ['SpacesService.updateMemberRole'](request: UpdateMemberRoleRequest): Effect.Effect<void, Error> {
137
+ return Effect.tryPromise({
138
+ try: async () => {
139
+ const identity = this._requireIdentity();
140
+ const space = this._spaceManager.spaces.get(request.spaceKey);
141
+ if (space == null) {
142
+ throw new SpaceNotFoundError(request.spaceKey);
143
+ }
144
+ if (!space.spaceState.hasMembershipManagementPermission(identity.identityKey)) {
145
+ throw new AuthorizationError({
146
+ message: 'No member management permission.',
147
+ context: {
148
+ spaceKey: space.key,
149
+ role: space.spaceState.getMemberRole(identity.identityKey),
150
+ },
151
+ });
152
+ }
153
+ const credentials = await createAdmissionCredentials(
154
+ identity.getIdentityCredentialSigner(),
155
+ request.memberKey,
156
+ space.key,
157
+ space.genesisFeedKey,
158
+ request.newRole,
159
+ space.spaceState.membershipChainHeads,
160
+ );
161
+ invariant(credentials[0].credential);
162
+ const spaceMemberCredential = credentials[0].credential.credential;
163
+ invariant(getCredentialAssertion(spaceMemberCredential)['@type'] === 'dxos.halo.credentials.SpaceMember');
164
+ await writeMessages(space.controlPipeline.writer, credentials);
165
+ },
166
+ catch: (error) => error as Error,
167
+ });
150
168
  }
151
169
 
152
- querySpaces(): Stream<QuerySpacesResponse> {
153
- return new Stream<QuerySpacesResponse>(({ next, ctx }) => {
170
+ ['SpacesService.querySpaces'](): EffectStream.Stream<QuerySpacesResponse, Error> {
171
+ return EffectStream.async<QuerySpacesResponse, Error>((emit) => {
172
+ const ctx = Context.default();
154
173
  const scheduler = new UpdateScheduler(
155
174
  ctx,
156
175
  async () => {
@@ -160,7 +179,7 @@ export class SpacesServiceImpl implements SpacesService {
160
179
  );
161
180
  log('update', () => ({ ids: spaces.map((space) => space.id) }));
162
181
  await this._updateMetrics();
163
- next({ spaces });
182
+ void emit.single({ spaces });
164
183
  },
165
184
  { maxFrequency: process.env.NODE_ENV === 'test' ? undefined : 2 },
166
185
  );
@@ -207,163 +226,216 @@ export class SpacesServiceImpl implements SpacesService {
207
226
  });
208
227
 
209
228
  if (!this._identityManager.identity) {
210
- next({ spaces: [] });
229
+ void emit.single({ spaces: [] });
211
230
  }
231
+
232
+ return Effect.promise(() => ctx.dispose());
212
233
  });
213
234
  }
214
235
 
215
- async postMessage({ spaceKey, channel, message }: PostMessageRequest): Promise<void> {
216
- const dataSpaceManager = await this._getDataSpaceManager();
217
- const space = dataSpaceManager.spaces.get(spaceKey) ?? raise(new SpaceNotFoundError(spaceKey));
218
- await space.postMessage(getChannelId(channel), message);
236
+ ['SpacesService.postMessage']({ spaceKey, channel, message }: PostMessageRequest): Effect.Effect<void, Error> {
237
+ return Effect.tryPromise({
238
+ try: async () => {
239
+ const dataSpaceManager = await this._getDataSpaceManager();
240
+ const space = dataSpaceManager.spaces.get(spaceKey) ?? raise(new SpaceNotFoundError(spaceKey));
241
+ await space.postMessage(getChannelId(channel), message);
242
+ },
243
+ catch: (error) => error as Error,
244
+ });
219
245
  }
220
246
 
221
- subscribeMessages({ spaceKey, channel }: SubscribeMessagesRequest): Stream<GossipMessage> {
222
- return new Stream<GossipMessage>(({ ctx, next }) => {
247
+ ['SpacesService.subscribeMessages']({
248
+ spaceKey,
249
+ channel,
250
+ }: SubscribeMessagesRequest): EffectStream.Stream<GossipMessage, Error> {
251
+ return EffectStream.async<GossipMessage, Error>((emit) => {
252
+ const ctx = Context.default();
223
253
  scheduleTask(ctx, async () => {
224
254
  const dataSpaceManager = await this._getDataSpaceManager();
225
255
  const space = dataSpaceManager.spaces.get(spaceKey) ?? raise(new SpaceNotFoundError(spaceKey));
226
256
  const handle = space.listen(getChannelId(channel), (message) => {
227
- next(message);
257
+ void emit.single(message);
228
258
  });
229
259
  ctx.onDispose(() => handle.unsubscribe());
230
260
  });
261
+
262
+ return Effect.promise(() => ctx.dispose());
231
263
  });
232
264
  }
233
265
 
234
- queryCredentials({ spaceKey, noTail }: QueryCredentialsRequest): Stream<Credential> {
235
- return new Stream(({ ctx, next, close }) => {
266
+ ['SpacesService.queryCredentials']({
267
+ spaceKey,
268
+ noTail,
269
+ }: QueryCredentialsRequest): EffectStream.Stream<Credential, Error> {
270
+ return EffectStream.async<Credential, Error>((emit) => {
271
+ const ctx = Context.default();
236
272
  const space = this._spaceManager.spaces.get(spaceKey) ?? raise(new SpaceNotFoundError(spaceKey));
237
273
 
238
274
  const processor: CredentialProcessor = {
239
275
  processCredential: async (credential) => {
240
- next(credential);
276
+ void emit.single(credential);
241
277
  },
242
278
  };
243
279
  ctx.onDispose(() => space.spaceState.removeCredentialProcessor(processor));
244
280
  scheduleTask(ctx, async () => {
245
281
  await space.spaceState.addCredentialProcessor(processor);
246
282
  if (noTail) {
247
- close();
283
+ void emit.end();
248
284
  }
249
285
  });
286
+
287
+ return Effect.promise(() => ctx.dispose());
250
288
  });
251
289
  }
252
290
 
253
- async writeCredentials({ spaceKey, credentials }: WriteCredentialsRequest): Promise<void> {
254
- const space = this._spaceManager.spaces.get(spaceKey) ?? raise(new SpaceNotFoundError(spaceKey));
255
- for (const credential of credentials ?? []) {
256
- if (credential.proof) {
257
- await space.controlPipeline.writer.write({ credential: { credential } });
258
- } else {
259
- invariant(!credential.id, 'Id on unsigned credentials is not allowed');
260
- invariant(this._identityManager.identity, 'Identity is not available');
261
- const signer = this._identityManager.identity.getIdentityCredentialSigner();
262
- invariant(credential.issuer.equals(signer.getIssuer()));
263
- const signedCredential = await signer.createCredential({
264
- subject: credential.subject.id,
265
- assertion: credential.subject.assertion,
266
- });
267
- await space.controlPipeline.writer.write({ credential: { credential: signedCredential } });
268
- }
269
- }
291
+ ['SpacesService.writeCredentials']({ spaceKey, credentials }: WriteCredentialsRequest): Effect.Effect<void, Error> {
292
+ return Effect.tryPromise({
293
+ try: async () => {
294
+ const space = this._spaceManager.spaces.get(spaceKey) ?? raise(new SpaceNotFoundError(spaceKey));
295
+ for (const credential of credentials ?? []) {
296
+ if (credential.proof) {
297
+ await space.controlPipeline.writer.write({ credential: { credential } });
298
+ } else {
299
+ invariant(!credential.id, 'Id on unsigned credentials is not allowed');
300
+ invariant(this._identityManager.identity, 'Identity is not available');
301
+ const signer = this._identityManager.identity.getIdentityCredentialSigner();
302
+ invariant(credential.issuer.equals(signer.getIssuer()));
303
+ const signedCredential = await signer.createCredential({
304
+ subject: credential.subject.id,
305
+ assertion: credential.subject.assertion,
306
+ });
307
+ await space.controlPipeline.writer.write({ credential: { credential: signedCredential } });
308
+ }
309
+ }
310
+ },
311
+ catch: (error) => error as Error,
312
+ });
270
313
  }
271
314
 
272
- async createEpoch({ spaceKey, migration, automergeRootUrl }: CreateEpochRequest): Promise<CreateEpochResponse> {
273
- const dataSpaceManager = await this._getDataSpaceManager();
274
- const space = dataSpaceManager.spaces.get(spaceKey) ?? raise(new SpaceNotFoundError(spaceKey));
275
- const result = await space.createEpoch({ migration, newAutomergeRoot: automergeRootUrl });
276
- return { epochCredential: result?.credential, controlTimeframe: result?.timeframe };
315
+ ['SpacesService.createEpoch']({
316
+ spaceKey,
317
+ migration,
318
+ automergeRootUrl,
319
+ }: CreateEpochRequest): Effect.Effect<CreateEpochResponse, Error> {
320
+ return Effect.tryPromise({
321
+ try: async () => {
322
+ const dataSpaceManager = await this._getDataSpaceManager();
323
+ const space = dataSpaceManager.spaces.get(spaceKey) ?? raise(new SpaceNotFoundError(spaceKey));
324
+ const result = await space.createEpoch({ migration, newAutomergeRoot: automergeRootUrl });
325
+ return { epochCredential: result?.credential, controlTimeframe: result?.timeframe };
326
+ },
327
+ catch: (error) => error as Error,
328
+ });
277
329
  }
278
330
 
279
- async admitContact(request: AdmitContactRequest): Promise<void> {
280
- const dataSpaceManager = await this._getDataSpaceManager();
281
- await dataSpaceManager.admitMember({
282
- spaceKey: request.spaceKey,
283
- identityKey: request.contact.identityKey,
284
- role: request.role,
331
+ ['SpacesService.admitContact'](request: AdmitContactRequest): Effect.Effect<void, Error> {
332
+ return Effect.tryPromise({
333
+ try: async () => {
334
+ const dataSpaceManager = await this._getDataSpaceManager();
335
+ await dataSpaceManager.admitMember({
336
+ spaceKey: request.spaceKey,
337
+ identityKey: request.contact.identityKey,
338
+ role: request.role,
339
+ });
340
+ },
341
+ catch: (error) => error as Error,
285
342
  });
286
343
  }
287
344
 
288
- async joinBySpaceKey({ spaceKey }: JoinBySpaceKeyRequest, options?: RequestOptions): Promise<JoinSpaceResponse> {
289
- const ctx = options?.ctx ?? Context.default();
290
- const dataSpaceManager = await this._getDataSpaceManager();
291
- const credential = await dataSpaceManager.requestSpaceAdmissionCredential(ctx, spaceKey);
292
- return this._joinByAdmission(ctx, { credential });
345
+ ['SpacesService.joinBySpaceKey']({ spaceKey }: JoinBySpaceKeyRequest): Effect.Effect<JoinSpaceResponse, Error> {
346
+ return Effect.tryPromise({
347
+ try: async () => {
348
+ const ctx = Context.default();
349
+ const dataSpaceManager = await this._getDataSpaceManager();
350
+ const credential = await dataSpaceManager.requestSpaceAdmissionCredential(ctx, spaceKey);
351
+ return this._joinByAdmission(ctx, { credential });
352
+ },
353
+ catch: (error) => error as Error,
354
+ });
293
355
  }
294
356
 
295
- async exportSpace(request: ExportSpaceRequest): Promise<ExportSpaceResponse> {
296
- assertArgument(SpaceId.isValid(request.spaceId), 'spaceId', 'Invalid space ID');
357
+ ['SpacesService.exportSpace'](request: ExportSpaceRequest): Effect.Effect<ExportSpaceResponse, Error> {
358
+ return Effect.tryPromise({
359
+ try: async () => {
360
+ assertArgument(SpaceId.isValid(request.spaceId), 'spaceId', 'Invalid space ID');
297
361
 
298
- const dataSpaceManager = await this._getDataSpaceManager();
299
- const space = dataSpaceManager.getSpaceById(request.spaceId) ?? raise(new Error('Space not found'));
362
+ const dataSpaceManager = await this._getDataSpaceManager();
363
+ const space = dataSpaceManager.getSpaceById(request.spaceId) ?? raise(new Error('Space not found'));
300
364
 
301
- const format = request.format ?? SpaceArchive.Format.BINARY;
302
- if (format === SpaceArchive.Format.JSON) {
303
- const archive = await writeSerializedSpaceArchive({ space, echoHost: this._echoHost });
304
- return { archive };
305
- }
365
+ const format = request.format ?? SpaceArchive.Format.BINARY;
366
+ if (format === SpaceArchive.Format.JSON) {
367
+ const archive = await writeSerializedSpaceArchive({ space, echoHost: this._echoHost });
368
+ return { archive };
369
+ }
306
370
 
307
- await using writer = await new SpaceArchiveWriter().open();
308
- await writer.begin({ spaceId: space.id });
309
- const rootUrl = space.automergeSpaceState.lastEpoch?.subject.assertion.automergeRoot;
310
- assertState(rootUrl, 'Space does not have a root URL');
311
- await writer.setCurrentRootUrl(rootUrl);
371
+ await using writer = await new SpaceArchiveWriter().open();
372
+ await writer.begin({ spaceId: space.id });
373
+ const rootUrl = space.automergeSpaceState.lastEpoch?.subject.assertion.automergeRoot;
374
+ assertState(rootUrl, 'Space does not have a root URL');
375
+ await writer.setCurrentRootUrl(rootUrl);
312
376
 
313
- for await (const [documentId, data] of space.getAllDocuments()) {
314
- await writer.writeDocument(documentId, data);
315
- }
377
+ for await (const [documentId, data] of space.getAllDocuments()) {
378
+ await writer.writeDocument(documentId, data);
379
+ }
316
380
 
317
- const feeds = await space.getAllFeeds();
318
- for (const feed of feeds) {
319
- const archiveBlocks = feed.blocks.map((block) => ({
320
- actorId: block.actorId,
321
- sequence: block.sequence,
322
- prevActorId: block.prevActorId,
323
- prevSequence: block.prevSequence,
324
- position: block.position,
325
- timestamp: block.timestamp,
326
- data: Buffer.from(block.data).toString('base64'),
327
- }));
328
- await writer.writeFeed(feed.feedId, feed.feedNamespace, archiveBlocks);
329
- }
381
+ const feeds = await space.getAllFeeds();
382
+ for (const feed of feeds) {
383
+ const archiveBlocks = feed.blocks.map((block) => ({
384
+ actorId: block.actorId,
385
+ sequence: block.sequence,
386
+ prevActorId: block.prevActorId,
387
+ prevSequence: block.prevSequence,
388
+ position: block.position,
389
+ timestamp: block.timestamp,
390
+ data: Buffer.from(block.data).toString('base64'),
391
+ }));
392
+ await writer.writeFeed(feed.feedId, feed.feedNamespace, archiveBlocks);
393
+ }
330
394
 
331
- const archive = await writer.finish();
332
- return { archive };
395
+ const archive = await writer.finish();
396
+ return { archive };
397
+ },
398
+ catch: (error) => error as Error,
399
+ });
333
400
  }
334
401
 
335
- async importSpace(request: ImportSpaceRequest, options?: RequestOptions): Promise<ImportSpaceResponse> {
336
- const ctx = options?.ctx ?? Context.default();
337
- const dataSpaceManager = await this._getDataSpaceManager();
402
+ ['SpacesService.importSpace'](request: ImportSpaceRequest): Effect.Effect<ImportSpaceResponse, Error> {
403
+ return Effect.tryPromise({
404
+ try: async () => {
405
+ const ctx = Context.default();
406
+ const dataSpaceManager = await this._getDataSpaceManager();
338
407
 
339
- const format = request.archive.format ?? detectSpaceArchiveFormat(request.archive);
340
- if (format === SpaceArchive.Format.JSON) {
341
- const serialized = readSerializedSpaceArchive(request.archive);
342
- const space = await dataSpaceManager.createSpace(ctx, { tags: request.tags });
343
- await this._hydrateSpaceFromSerialized(space, serialized);
344
- await this._updateMetrics();
345
- return { newSpaceId: space.id };
346
- }
408
+ const format = request.archive.format ?? detectSpaceArchiveFormat(request.archive);
409
+ if (format === SpaceArchive.Format.JSON) {
410
+ const serialized = readSerializedSpaceArchive(request.archive);
411
+ const space = await dataSpaceManager.createSpace(ctx, { tags: request.tags });
412
+ await this._hydrateSpaceFromSerialized(space, serialized);
413
+ await this._updateMetrics();
414
+ return { newSpaceId: space.id };
415
+ }
347
416
 
348
- const extracted = await extractSpaceArchive(request.archive);
349
- invariant(extracted.metadata.echo?.currentRootUrl, 'Space archive does not contain a root URL');
350
- const space = await dataSpaceManager.createSpace(ctx, {
351
- documents: extracted.documents,
352
- rootUrl: extracted.metadata.echo?.currentRootUrl as AutomergeUrl,
353
- tags: request.tags,
417
+ const extracted = await extractSpaceArchive(request.archive);
418
+ invariant(extracted.metadata.echo?.currentRootUrl, 'Space archive does not contain a root URL');
419
+ const space = await dataSpaceManager.createSpace(ctx, {
420
+ documents: extracted.documents,
421
+ rootUrl: extracted.metadata.echo?.currentRootUrl as AutomergeUrl,
422
+ tags: request.tags,
423
+ });
424
+ await this._updateMetrics();
425
+ return { newSpaceId: space.id };
426
+ },
427
+ catch: (error) => error as Error,
354
428
  });
355
- await this._updateMetrics();
356
- return { newSpaceId: space.id };
357
429
  }
358
430
 
359
431
  /**
360
432
  * Populate a freshly-created space with the objects and feed messages described in a {@link SerializedSpace}.
361
433
  *
362
434
  * Objects are written directly into the space's automerge root document as inline
363
- * {@link EntityStructure} entries; feed messages are appended to the appropriate queue
364
- * via {@link EchoHost.queuesService}.
435
+ * {@link EntityStructure} entries; feed messages are appended to the appropriate feed
436
+ * via {@link EchoHost.feedService}.
365
437
  */
366
- private async _hydrateSpaceFromSerialized(
438
+ private async '_hydrateSpaceFromSerialized'(
367
439
  space: DataSpace,
368
440
  serialized: ReturnType<typeof readSerializedSpaceArchive>,
369
441
  ): Promise<void> {
@@ -387,19 +459,26 @@ export class SpacesServiceImpl implements SpacesService {
387
459
  const namespace =
388
460
  feed.namespace === 'trace' ? FeedProtocol.WellKnownNamespaces.trace : FeedProtocol.WellKnownNamespaces.data;
389
461
  try {
390
- await this._echoHost.queuesService.insertIntoQueue({
391
- spaceId: space.id,
392
- queueId: feed.feedObjectId,
393
- subspaceTag: namespace,
394
- objects: feed.messages.map((message) => JSON.stringify(message)),
395
- });
462
+ // Handlers are served, not called directly; bridge to a client in-process for this write.
463
+ const feedService = this._echoHost.feedService;
464
+ await EffectEx.runPromise(
465
+ Effect.gen(function* () {
466
+ const feedClient = yield* makeInProcessClient(FeedService.Rpcs, feedService);
467
+ yield* feedClient.FeedService.insertIntoFeed({
468
+ spaceId: space.id,
469
+ feedId: feed.feedObjectId,
470
+ subspaceTag: namespace,
471
+ objects: feed.messages.map((message) => JSON.stringify(message)),
472
+ });
473
+ }).pipe(Effect.scoped),
474
+ );
396
475
  } catch (err) {
397
476
  log.warn('failed to import feed data', { feedObjectId: feed.feedObjectId, error: err });
398
477
  }
399
478
  }
400
479
  }
401
480
 
402
- private async _joinByAdmission(ctx: Context, { credential }: ContactAdmission): Promise<JoinSpaceResponse> {
481
+ private async '_joinByAdmission'(ctx: Context, { credential }: ContactAdmission): Promise<JoinSpaceResponse> {
403
482
  const assertion = getCredentialAssertion(credential);
404
483
  invariant(assertion['@type'] === 'dxos.halo.credentials.SpaceMember', 'Invalid credential');
405
484
  const myIdentity = this._identityManager.identity;
@@ -419,7 +498,7 @@ export class SpacesServiceImpl implements SpacesService {
419
498
  return { space: await this._serializeSpace(dataSpace) };
420
499
  }
421
500
 
422
- private async _serializeSpace(space: DataSpace): Promise<Space> {
501
+ private async '_serializeSpace'(space: DataSpace): Promise<Space> {
423
502
  return {
424
503
  id: space.id,
425
504
  spaceKey: space.key,
@@ -472,7 +551,7 @@ export class SpacesServiceImpl implements SpacesService {
472
551
  };
473
552
  }
474
553
 
475
- private _requireIdentity() {
554
+ private '_requireIdentity'() {
476
555
  if (!this._identityManager.identity) {
477
556
  throw new IdentityNotInitializedError({
478
557
  message: 'This device has no HALO identity available. See https://docs.dxos.org/guide/platform/halo',
@@ -481,7 +560,7 @@ export class SpacesServiceImpl implements SpacesService {
481
560
  return this._identityManager.identity;
482
561
  }
483
562
 
484
- private async _updateMetrics(): Promise<void> {
563
+ private async '_updateMetrics'(): Promise<void> {
485
564
  const dataSpaceManager = await this._getDataSpaceManager();
486
565
  const identity = this._identityManager.identity?.identityKey.truncate();
487
566
  if (identity) {
@@ -5,12 +5,14 @@
5
5
  import path from 'node:path';
6
6
 
7
7
  import { PublicKey } from '@dxos/keys';
8
- import { createLevel as createKV } from '@dxos/kv-store';
9
8
  import { type Runtime } from '@dxos/protocols/proto/dxos/config';
10
9
 
11
10
  import { getRootPath, isPersistent } from './util';
12
11
 
13
12
  export const createLevel = async (config: Runtime.Client.Storage) => {
13
+ // Imported here rather than at module scope so that this barrel, which the client pulls in on every
14
+ // startup, does not bind `level`'s native addon — a compiled binary cannot carry one.
15
+ const { createLevel: createKV } = await import('@dxos/kv-store/level');
14
16
  const persistent = isPersistent(config);
15
17
  const storagePath = persistent ? path.join(getRootPath(config), 'level') : `/tmp/dxos-${PublicKey.random().toHex()}`;
16
18
  const level = createKV(storagePath);