@dxos/client-services 0.10.0 → 0.11.1

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,25 +3,26 @@
3
3
  //
4
4
 
5
5
  import * as Reactivity from '@effect/experimental/Reactivity';
6
+ import type * as RpcClient from '@effect/rpc/RpcClient';
7
+ import type * as RpcServer from '@effect/rpc/RpcServer';
6
8
  import type * as SqlClient from '@effect/sql/SqlClient';
9
+ import * as Context_ from 'effect/Context';
7
10
  import * as Effect from 'effect/Effect';
11
+ import * as Exit from 'effect/Exit';
8
12
  import * as Layer from 'effect/Layer';
9
13
  import * as ManagedRuntime from 'effect/ManagedRuntime';
14
+ import * as Scope from 'effect/Scope';
10
15
 
11
16
  import { Trigger } from '@dxos/async';
12
- import { DEFAULT_WORKER_BROADCAST_CHANNEL } from '@dxos/client-protocol';
13
17
  import { type Config } from '@dxos/config';
14
18
  import { Context } from '@dxos/context';
19
+ import { EffectEx } from '@dxos/effect';
15
20
  import { invariant } from '@dxos/invariant';
16
21
  import { log } from '@dxos/log';
17
- import {
18
- MemorySignalManager,
19
- MemorySignalManagerContext,
20
- WebsocketSignalManager,
21
- setIdentityTags,
22
- } from '@dxos/messaging';
22
+ import { MemorySignalManager, MemorySignalManagerContext, setIdentityTags } from '@dxos/messaging';
23
23
  import { RtcTransportProxyFactory } from '@dxos/network-manager';
24
- import { type RpcPort } from '@dxos/rpc';
24
+ import { makeInProcessClient } from '@dxos/protocols';
25
+ import { DevicesService, IdentityService } from '@dxos/protocols/rpc';
25
26
  import * as SqlExport from '@dxos/sql-sqlite/SqlExport';
26
27
  import * as SqliteClient from '@dxos/sql-sqlite/SqliteClient';
27
28
  import * as SqlTransaction from '@dxos/sql-sqlite/SqlTransaction';
@@ -30,16 +31,17 @@ import { type MaybePromise } from '@dxos/util';
30
31
  import { ClientServicesHost } from '../services';
31
32
  import { WorkerSession } from './worker-session';
32
33
 
33
- // NOTE: Keep as RpcPorts to avoid dependency on @dxos/rpc-tunnel so we don't depend on browser-specific apis.
34
+ // Session transports are effect-rpc protocol layers handed over by the worker framework: appProtocol
35
+ // serves the client services (+ WorkerService); systemProtocol carries the reverse-direction
36
+ // BridgeService (worker→tab).
34
37
  export type CreateSessionProps = {
35
- appPort: RpcPort;
36
- systemPort: RpcPort;
37
- shellPort?: RpcPort;
38
+ appProtocol: RpcServer.Protocol['Type'];
39
+ systemProtocol: RpcClient.Protocol['Type'];
40
+ shellPort?: MessagePort;
38
41
  onClose?: () => Promise<void>;
39
42
  };
40
43
 
41
44
  export type WorkerRuntimeOptions = {
42
- channel?: string;
43
45
  configProvider: () => MaybePromise<Config>;
44
46
  acquireLock: () => Promise<void>;
45
47
  releaseLock: () => void;
@@ -57,241 +59,233 @@ export type WorkerRuntimeOptions = {
57
59
  };
58
60
 
59
61
  /**
60
- * Runtime for the shared and dedciated worker.
61
- * Manages connections from proxies (in tabs).
62
- * Tabs make requests to the `ClientServicesHost`, and provide a WebRTC gateway.
62
+ * Effect service surface for the dedicated-worker runtime.
63
+ *
64
+ * Manages connections from proxies (in tabs): tabs make requests to the `ClientServicesHost`, and
65
+ * provide a WebRTC gateway. Lifecycle (`start` / `stop`) is caller-driven — the worker framework
66
+ * builds the runtime after receiving init config, then drives sessions for their lifetime — so these
67
+ * are explicit programs rather than Layer finalizers.
63
68
  */
64
- export class WorkerRuntime {
65
- private readonly _configProvider: () => MaybePromise<Config>;
66
- private readonly _acquireLock: () => Promise<void>;
67
- private readonly _releaseLock: () => void;
68
- private readonly _onStop?: () => Promise<void>;
69
- private readonly _transportFactory = new RtcTransportProxyFactory();
70
- private readonly _ready = new Trigger<Error | undefined>();
71
- private readonly _sessions = new Set<WorkerSession>();
72
- private readonly _clientServices!: ClientServicesHost;
73
- private readonly _channel: string;
74
- private readonly _automaticallyConnectWebrtc: boolean;
75
- private readonly _livenessLock = new WebLockWrapper(`@dxos/client-services/WorkerRuntime/${crypto.randomUUID()}`);
76
- private _broadcastChannel?: BroadcastChannel;
77
- private _sessionForNetworking?: WorkerSession; // TODO(burdon): Expose to client QueryStatusResponse.
78
- private _config!: Config;
79
- private _signalMetadataTags: any = { runtime: 'worker-runtime' };
80
- private _signalTelemetryEnabled: boolean = false;
81
- private _runtime!: ManagedRuntime.ManagedRuntime<
82
- SqlTransaction.SqlTransaction | SqlClient.SqlClient | SqlExport.SqlExport,
83
- never
84
- >;
85
-
86
- constructor({
87
- channel = DEFAULT_WORKER_BROADCAST_CHANNEL,
88
- configProvider,
89
- acquireLock,
90
- releaseLock,
91
- onStop,
92
- automaticallyConnectWebrtc = true,
93
- sqliteLayer,
94
- }: WorkerRuntimeOptions) {
95
- this._configProvider = configProvider;
96
- this._acquireLock = acquireLock;
97
- this._releaseLock = releaseLock;
98
- this._onStop = onStop;
99
- this._channel = channel;
100
- if (sqliteLayer) {
101
- log.warn('Using testing SQLite layer');
102
- }
103
- this._runtime = ManagedRuntime.make(
104
- SqlTransaction.layer
105
- .pipe(Layer.provideMerge(sqliteLayer ?? LocalSqliteOpfsLayer), Layer.provideMerge(Reactivity.layer))
106
- .pipe(Layer.orDie),
107
- );
108
- this._clientServices = new ClientServicesHost({
109
- callbacks: {
110
- onReset: async () => this.stop(),
111
- },
112
- runtime: this._runtime.runtimeEffect,
113
- runtimeProps: {
114
- // Auto-activate spaces that were previously active after leader changeover.
115
- autoActivateSpaces: true,
116
- },
117
- });
118
- this._automaticallyConnectWebrtc = automaticallyConnectWebrtc;
119
- }
69
+ export interface WorkerRuntimeService {
70
+ /** The client services host served to connected tabs. */
71
+ readonly host: ClientServicesHost;
72
+ /** Resolve config, open the services host, and signal readiness. Never fails: startup errors are surfaced to session callers via the readiness gate. */
73
+ readonly start: () => Effect.Effect<void>;
74
+ /** Tear down sessions' host, dispose the runtime, release the storage lock, and run `onStop`. Idempotent. */
75
+ readonly stop: () => Effect.Effect<void>;
76
+ /** Open a new tab session over the supplied effect-rpc protocols and register it for WebRTC bridging. */
77
+ readonly createSession: (props: CreateSessionProps) => Effect.Effect<WorkerSession>;
78
+ /** Route the WebRTC bridge through the given session (or disconnect when `undefined`). */
79
+ readonly connectWebrtcBridge: (session: WorkerSession | undefined) => Effect.Effect<void>;
80
+ }
120
81
 
121
- get host() {
122
- return this._clientServices;
123
- }
82
+ /**
83
+ * Context tag for the dedicated-worker runtime service. Provided by {@link layerWorkerRuntime}.
84
+ */
85
+ export class WorkerRuntime extends Context_.Tag('@dxos/client-services/WorkerRuntime')<
86
+ WorkerRuntime,
87
+ WorkerRuntimeService
88
+ >() {}
124
89
 
125
- get livenessLockKey(): string {
126
- return this._livenessLock.key;
90
+ /**
91
+ * Constructs the {@link WorkerRuntimeService}. The SQLite {@link ManagedRuntime} and
92
+ * {@link ClientServicesHost} are built eagerly; the async open sequence runs in {@link start}.
93
+ */
94
+ export const makeWorkerRuntime = ({
95
+ configProvider,
96
+ acquireLock,
97
+ releaseLock,
98
+ onStop,
99
+ automaticallyConnectWebrtc = true,
100
+ sqliteLayer,
101
+ }: WorkerRuntimeOptions): WorkerRuntimeService => {
102
+ const transportFactory = new RtcTransportProxyFactory();
103
+ const ready = new Trigger<Error | undefined>();
104
+ const sessions = new Set<WorkerSession>();
105
+ const signalMetadataTags: any = { runtime: 'worker-runtime' };
106
+
107
+ let stopped = false;
108
+ let sessionForNetworking: WorkerSession | undefined;
109
+ let config: Config;
110
+ let serviceScope: Scope.CloseableScope | undefined;
111
+
112
+ if (sqliteLayer) {
113
+ log.warn('Using testing SQLite layer');
127
114
  }
128
115
 
129
- async start(): Promise<void> {
130
- log('starting...');
131
- try {
132
- log('worker-runtime: acquiring liveness lock (background)');
133
- void this._livenessLock.acquire();
116
+ const runtime = ManagedRuntime.make(
117
+ SqlTransaction.layer
118
+ .pipe(Layer.provideMerge(sqliteLayer ?? LocalSqliteOpfsLayer), Layer.provideMerge(Reactivity.layer))
119
+ .pipe(Layer.orDie),
120
+ );
134
121
 
135
- // Steal the lock from the other worker.
136
- log('worker-runtime: broadcasting stop to displace previous worker');
137
- this._broadcastChannel = new BroadcastChannel(this._channel);
138
- this._broadcastChannel.postMessage({ action: 'stop' });
139
- this._broadcastChannel.onmessage = async (event) => {
140
- if (event.data?.action === 'stop') {
141
- log('worker-runtime: received stop broadcast');
142
- await this.stop();
122
+ const stop = (): Effect.Effect<void> =>
123
+ Effect.promise(async () => {
124
+ if (stopped) {
125
+ return;
126
+ }
127
+ stopped = true;
128
+ // Release the lock to notify remote clients that the worker is terminating.
129
+ releaseLock();
130
+ // Always dispose the SQLite runtime and run onStop, even if host / scope teardown rejects —
131
+ // otherwise a failed close would leak the runtime and skip the shutdown signal.
132
+ try {
133
+ await clientServices.close(Context.default());
134
+ if (serviceScope) {
135
+ await EffectEx.runPromise(Scope.close(serviceScope, Exit.void));
136
+ serviceScope = undefined;
143
137
  }
144
- };
145
-
146
- log('worker-runtime: acquiring storage lock');
147
- await this._acquireLock();
148
- log('worker-runtime: storage lock acquired, resolving config');
149
- this._config = await this._configProvider();
150
- log('worker-runtime: config resolved');
151
- this._signalTelemetryEnabled = this._config.get('runtime.client.signalTelemetryEnabled') ?? false;
152
- const observabilityGroup = this._config.get('runtime.client.observabilityGroup');
153
- if (observabilityGroup) {
154
- this._signalMetadataTags.group = observabilityGroup;
138
+ } finally {
139
+ await runtime.dispose();
140
+ await onStop?.();
155
141
  }
156
- const signals = this._config.get('runtime.services.signaling');
157
- log('worker-runtime: initializing client services host');
158
- this._clientServices.initialize({
159
- config: this._config,
160
- signalManager: this._config.get('runtime.client.edgeFeatures')?.signaling
161
- ? undefined
162
- : signals
163
- ? new WebsocketSignalManager(signals, () => (this._signalTelemetryEnabled ? this._signalMetadataTags : {}))
164
- : new MemorySignalManager(new MemorySignalManagerContext()), // TODO(dmaretskyi): Inject this context.
165
- transportFactory: this._transportFactory,
166
- });
167
- log('worker-runtime: client services host initialized, opening');
168
-
169
- await this._clientServices.open(new Context());
170
- log('worker-runtime: client services host opened, signalling ready');
171
- this._ready.wake(undefined);
172
- log('started');
173
- setIdentityTags({
174
- identityService: this._clientServices.services.IdentityService!,
175
- devicesService: this._clientServices.services.DevicesService!,
176
- setTag: (k: string, v: string) => {
177
- this._signalMetadataTags[k] = v;
178
- },
179
- });
180
- } catch (err: any) {
181
- this._ready.wake(err);
182
- log.error('starting', err);
183
- }
184
- }
185
-
186
- async stop(): Promise<void> {
187
- // Release the lock to notify remote clients that the worker is terminating.
188
- this._releaseLock();
189
- this._broadcastChannel?.close();
190
- this._broadcastChannel = undefined;
191
- await this._clientServices.close(Context.default());
192
- await this._runtime.dispose();
193
- await this._onStop?.();
194
- await this._livenessLock.release();
195
- }
142
+ });
196
143
 
197
- /**
198
- * Update signaling telemetry tags from a client-supplied config overlay.
199
- *
200
- * The worker services outlive individual client connections, so the first client seeds the
201
- * worker's core config (storage, signaling, edge features). For fields that can legitimately
202
- * differ per tab — `observabilityGroup` and `signalTelemetryEnabled` — this method lets later
203
- * connections refresh the signal metadata the worker attaches to its signaling requests
204
- * (last-writer-wins, matching the pre-DX-930 per-session RPC behaviour).
205
- */
206
- updateSignalMetadata(config: Config): void {
207
- const observabilityGroup = config.get('runtime.client.observabilityGroup');
208
- if (observabilityGroup) {
209
- this._signalMetadataTags.group = observabilityGroup;
210
- } else {
211
- // Clear stale group so a later config that removes observabilityGroup stops attributing
212
- // telemetry to the previous client's group (last-writer-wins).
213
- delete this._signalMetadataTags.group;
144
+ const clientServices = new ClientServicesHost({
145
+ callbacks: {
146
+ onReset: async () => {
147
+ await EffectEx.runPromise(stop());
148
+ },
149
+ },
150
+ runtime: runtime.runtimeEffect,
151
+ runtimeProps: {
152
+ // Auto-activate spaces that were previously active after leader changeover.
153
+ autoActivateSpaces: true,
154
+ },
155
+ });
156
+
157
+ const connectBridge = (session: WorkerSession | undefined): void => {
158
+ sessionForNetworking = session;
159
+ transportFactory.setBridgeService(session?.bridgeService);
160
+ };
161
+
162
+ // Selects one of the existing sessions for WebRTC networking.
163
+ const reconnectWebrtc = Effect.sync(() => {
164
+ log('reconnecting webrtc...');
165
+ // Drop the current session if it has since closed.
166
+ if (sessionForNetworking && !sessions.has(sessionForNetworking)) {
167
+ sessionForNetworking = undefined;
214
168
  }
215
- const signalTelemetryEnabled = config.get('runtime.client.signalTelemetryEnabled');
216
- if (signalTelemetryEnabled !== undefined) {
217
- this._signalTelemetryEnabled = signalTelemetryEnabled;
169
+ if (!sessionForNetworking) {
170
+ connectBridge(Array.from(sessions).find((session) => session.bridgeService));
218
171
  }
219
- }
220
-
221
- /**
222
- * Create a new session.
223
- */
224
- async createSession({ appPort, systemPort, shellPort, onClose }: CreateSessionProps): Promise<WorkerSession> {
225
- const session = new WorkerSession({
226
- serviceHost: this._clientServices,
227
- appPort,
228
- systemPort,
229
- shellPort,
230
- readySignal: this._ready,
231
- });
232
-
233
- // When tab is closed or client is destroyed.
234
- session.onClose.set(async () => {
235
- this._sessions.delete(session);
236
- if (this._sessions.size === 0) {
237
- // Terminate the worker when all sessions are closed.
238
- await this.stop();
239
- } else {
240
- if (this._automaticallyConnectWebrtc) {
241
- this._reconnectWebrtc();
172
+ });
173
+
174
+ const start = (): Effect.Effect<void> =>
175
+ Effect.promise(async () => {
176
+ log('starting...');
177
+ try {
178
+ log('worker-runtime: acquiring storage lock');
179
+ await acquireLock();
180
+ log('worker-runtime: storage lock acquired, resolving config');
181
+ config = await configProvider();
182
+ log('worker-runtime: config resolved');
183
+ const observabilityGroup = config.get('runtime.client.observabilityGroup');
184
+ if (observabilityGroup) {
185
+ signalMetadataTags.group = observabilityGroup;
242
186
  }
187
+ log('worker-runtime: initializing client services host');
188
+ clientServices.initialize({
189
+ config,
190
+ // Edge signaling is created in the services host from the edge connection; otherwise fall
191
+ // back to an isolated in-memory manager (KUBE `WebsocketSignalManager` removed).
192
+ signalManager: config.get('runtime.client.edgeFeatures')?.signaling
193
+ ? undefined
194
+ : new MemorySignalManager(new MemorySignalManagerContext()), // TODO(dmaretskyi): Inject this context.
195
+ transportFactory,
196
+ });
197
+ log('worker-runtime: client services host initialized, opening');
198
+
199
+ await clientServices.open(new Context());
200
+ log('worker-runtime: client services host opened, signalling ready');
201
+ ready.wake(undefined);
202
+ log('started');
203
+ // Bridge the host identity/devices Handlers to the effect-rpc client surface in-process.
204
+ serviceScope = Effect.runSync(Scope.make());
205
+ const { IdentityService: identityHandlers, DevicesService: devicesHandlers } = clientServices.services;
206
+ invariant(identityHandlers, 'IdentityService handler not available');
207
+ invariant(devicesHandlers, 'DevicesService handler not available');
208
+ const [identityService, devicesService] = await EffectEx.runPromise(
209
+ Effect.all([
210
+ makeInProcessClient(IdentityService.Rpcs, identityHandlers),
211
+ makeInProcessClient(DevicesService.Rpcs, devicesHandlers),
212
+ ]).pipe(Effect.provideService(Scope.Scope, serviceScope)),
213
+ );
214
+ setIdentityTags({
215
+ identityService,
216
+ devicesService,
217
+ setTag: (key: string, value: string) => {
218
+ signalMetadataTags[key] = value;
219
+ },
220
+ });
221
+ } catch (err: any) {
222
+ ready.wake(err);
223
+ log.error('starting', err);
243
224
  }
244
- await onClose?.();
245
225
  });
246
226
 
247
- await session.open();
248
- // A worker can only service one origin currently
249
- invariant(
250
- !this._signalMetadataTags.origin || this._signalMetadataTags.origin === session.origin,
251
- `worker origin changed from ${this._signalMetadataTags.origin} to ${session.origin}?`,
252
- );
253
- this._signalMetadataTags.origin = session.origin;
254
- this._sessions.add(session);
227
+ const createSession = ({
228
+ appProtocol,
229
+ systemProtocol,
230
+ shellPort,
231
+ onClose,
232
+ }: CreateSessionProps): Effect.Effect<WorkerSession> =>
233
+ Effect.gen(function* () {
234
+ const session = new WorkerSession({
235
+ serviceHost: clientServices,
236
+ appProtocol,
237
+ systemProtocol,
238
+ shellPort,
239
+ readySignal: ready,
240
+ });
255
241
 
256
- if (this._automaticallyConnectWebrtc) {
257
- this._reconnectWebrtc();
258
- }
242
+ // When tab is closed or client is destroyed.
243
+ session.onClose.set(async () => {
244
+ await EffectEx.runPromise(
245
+ Effect.gen(function* () {
246
+ sessions.delete(session);
247
+ if (sessions.size === 0) {
248
+ // Terminate the worker when all sessions are closed.
249
+ yield* stop();
250
+ } else if (automaticallyConnectWebrtc) {
251
+ yield* reconnectWebrtc;
252
+ }
253
+ }),
254
+ );
255
+ await onClose?.();
256
+ });
259
257
 
260
- return session;
261
- }
258
+ yield* session.open();
259
+ // A worker can only service one origin currently.
260
+ invariant(
261
+ !signalMetadataTags.origin || signalMetadataTags.origin === session.origin,
262
+ `worker origin changed from ${signalMetadataTags.origin} to ${session.origin}?`,
263
+ );
264
+ signalMetadataTags.origin = session.origin;
265
+ sessions.add(session);
266
+
267
+ if (automaticallyConnectWebrtc) {
268
+ yield* reconnectWebrtc;
269
+ }
262
270
 
263
- /**
264
- * Connects the WebRTC bridge to the specified session.
265
- * If no session is provided, disconnects the WebRTC bridge.
266
- *
267
- * Called automatically if `automaticallyConnectWebrtc` is true.
268
- *
269
- * @param session The session to connect the WebRTC bridge to.
270
- */
271
- connectWebrtcBridge(session: WorkerSession | undefined): void {
272
- this._sessionForNetworking = session;
273
- this._transportFactory.setBridgeService(session?.bridgeService);
274
- }
271
+ return session;
272
+ });
275
273
 
276
- /**
277
- * Selects one of the existing session for WebRTC networking.
278
- */
279
- private _reconnectWebrtc(): void {
280
- log('reconnecting webrtc...');
281
- // Check if current session is already closed.
282
- if (this._sessionForNetworking) {
283
- if (!this._sessions.has(this._sessionForNetworking)) {
284
- this._sessionForNetworking = undefined;
285
- }
286
- }
274
+ return {
275
+ host: clientServices,
276
+ start,
277
+ stop,
278
+ createSession,
279
+ connectWebrtcBridge: (session) => Effect.sync(() => connectBridge(session)),
280
+ };
281
+ };
287
282
 
288
- // Select existing session.
289
- if (!this._sessionForNetworking) {
290
- const selected = Array.from(this._sessions).find((session) => session.bridgeService);
291
- this.connectWebrtcBridge(selected);
292
- }
293
- }
294
- }
283
+ /**
284
+ * Layer providing the {@link WorkerRuntime} service. The service is constructed synchronously;
285
+ * callers drive `start` / `stop` explicitly (see {@link WorkerRuntimeService}).
286
+ */
287
+ export const layerWorkerRuntime = (options: WorkerRuntimeOptions): Layer.Layer<WorkerRuntime> =>
288
+ Layer.sync(WorkerRuntime, () => makeWorkerRuntime(options));
295
289
 
296
290
  const DB_NAME = 'DXOS';
297
291
 
@@ -317,35 +311,3 @@ const LocalSqliteOpfsLayer = SqlExportLayer.pipe(
317
311
  Layer.provideMerge(SqliteClient.layerOpfs({ dbName: DB_NAME })),
318
312
  Layer.provideMerge(Reactivity.layer),
319
313
  );
320
-
321
- // TODO(wittjosiah): Factor out to a separate module.
322
- class WebLockWrapper {
323
- readonly #key: string;
324
- #release?: () => void;
325
-
326
- constructor(key: string) {
327
- this.#key = key;
328
- }
329
-
330
- get key(): string {
331
- return this.#key;
332
- }
333
-
334
- acquire(options: LockOptions = {}) {
335
- return navigator.locks.request(this.#key, options, async () => {
336
- await new Promise<void>((resolve) => {
337
- this.#release = resolve;
338
- }); // Blocks for the duration of the worker's lifetime.
339
- this.#release = undefined;
340
- });
341
- }
342
-
343
- release() {
344
- this.#release?.();
345
- this.#release = undefined;
346
- }
347
-
348
- [Symbol.dispose]() {
349
- this.release();
350
- }
351
- }