@dxos/client-services 0.8.4-main.c85a9c8dae → 0.8.4-main.cb12b3f963

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 (199) hide show
  1. package/dist/lib/browser/{chunk-MQ6PWJ76.mjs → chunk-TZQLGPMV.mjs} +1596 -3099
  2. package/dist/lib/browser/chunk-TZQLGPMV.mjs.map +7 -0
  3. package/dist/lib/browser/{chunk-NQSC7HOE.mjs → chunk-XJRPB3GA.mjs} +1 -1
  4. package/dist/lib/browser/index.mjs +106 -194
  5. package/dist/lib/browser/index.mjs.map +3 -3
  6. package/dist/lib/browser/meta.json +1 -1
  7. package/dist/lib/browser/packlets/diagnostics/browser-diagnostics-broadcast.mjs +1 -6
  8. package/dist/lib/browser/packlets/diagnostics/browser-diagnostics-broadcast.mjs.map +2 -2
  9. package/dist/lib/browser/packlets/diagnostics/diagnostics-broadcast.mjs +1 -1
  10. package/dist/lib/browser/packlets/locks/browser.mjs +9 -49
  11. package/dist/lib/browser/packlets/locks/browser.mjs.map +2 -2
  12. package/dist/lib/browser/packlets/locks/node.mjs +4 -22
  13. package/dist/lib/browser/packlets/locks/node.mjs.map +2 -2
  14. package/dist/lib/browser/testing/index.mjs +9 -22
  15. package/dist/lib/browser/testing/index.mjs.map +3 -3
  16. package/dist/lib/node-esm/{chunk-PKEGMOQ4.mjs → chunk-2DT3MZRL.mjs} +1 -1
  17. package/dist/lib/node-esm/{chunk-GUAL4U7S.mjs → chunk-6DX3BNLB.mjs} +1596 -3099
  18. package/dist/lib/node-esm/chunk-6DX3BNLB.mjs.map +7 -0
  19. package/dist/lib/node-esm/index.mjs +106 -194
  20. package/dist/lib/node-esm/index.mjs.map +3 -3
  21. package/dist/lib/node-esm/meta.json +1 -1
  22. package/dist/lib/node-esm/packlets/diagnostics/browser-diagnostics-broadcast.mjs +1 -6
  23. package/dist/lib/node-esm/packlets/diagnostics/browser-diagnostics-broadcast.mjs.map +2 -2
  24. package/dist/lib/node-esm/packlets/diagnostics/diagnostics-broadcast.mjs +1 -1
  25. package/dist/lib/node-esm/packlets/locks/browser.mjs +9 -49
  26. package/dist/lib/node-esm/packlets/locks/browser.mjs.map +2 -2
  27. package/dist/lib/node-esm/packlets/locks/node.mjs +4 -22
  28. package/dist/lib/node-esm/packlets/locks/node.mjs.map +2 -2
  29. package/dist/lib/node-esm/testing/index.mjs +9 -22
  30. package/dist/lib/node-esm/testing/index.mjs.map +3 -3
  31. package/dist/types/src/index.d.ts +1 -0
  32. package/dist/types/src/index.d.ts.map +1 -1
  33. package/dist/types/src/packlets/agents/edge-agent-manager.d.ts +3 -2
  34. package/dist/types/src/packlets/agents/edge-agent-manager.d.ts.map +1 -1
  35. package/dist/types/src/packlets/agents/edge-agent-service.d.ts +2 -1
  36. package/dist/types/src/packlets/agents/edge-agent-service.d.ts.map +1 -1
  37. package/dist/types/src/packlets/devices/devices-service.d.ts.map +1 -1
  38. package/dist/types/src/packlets/devtools/devtools.d.ts.map +1 -1
  39. package/dist/types/src/packlets/devtools/feeds.d.ts.map +1 -1
  40. package/dist/types/src/packlets/devtools/keys.d.ts.map +1 -1
  41. package/dist/types/src/packlets/devtools/metadata.d.ts.map +1 -1
  42. package/dist/types/src/packlets/devtools/network.d.ts.map +1 -1
  43. package/dist/types/src/packlets/devtools/spaces.d.ts.map +1 -1
  44. package/dist/types/src/packlets/diagnostics/browser-diagnostics-broadcast.d.ts.map +1 -1
  45. package/dist/types/src/packlets/diagnostics/diagnostics-broadcast.d.ts.map +1 -1
  46. package/dist/types/src/packlets/diagnostics/diagnostics-collector.d.ts.map +1 -1
  47. package/dist/types/src/packlets/diagnostics/diagnostics.d.ts +2 -3
  48. package/dist/types/src/packlets/diagnostics/diagnostics.d.ts.map +1 -1
  49. package/dist/types/src/packlets/identity/authenticator.d.ts.map +1 -1
  50. package/dist/types/src/packlets/identity/contacts-service.d.ts.map +1 -1
  51. package/dist/types/src/packlets/identity/identity-manager.d.ts +3 -3
  52. package/dist/types/src/packlets/identity/identity-manager.d.ts.map +1 -1
  53. package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts +6 -5
  54. package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts.map +1 -1
  55. package/dist/types/src/packlets/identity/identity-service.d.ts +6 -10
  56. package/dist/types/src/packlets/identity/identity-service.d.ts.map +1 -1
  57. package/dist/types/src/packlets/identity/identity.d.ts +6 -9
  58. package/dist/types/src/packlets/identity/identity.d.ts.map +1 -1
  59. package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts +2 -1
  60. package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts.map +1 -1
  61. package/dist/types/src/packlets/invitations/edge-invitation-handler.d.ts +1 -1
  62. package/dist/types/src/packlets/invitations/edge-invitation-handler.d.ts.map +1 -1
  63. package/dist/types/src/packlets/invitations/invitation-guest-extenstion.d.ts.map +1 -1
  64. package/dist/types/src/packlets/invitations/invitation-host-extension.d.ts.map +1 -1
  65. package/dist/types/src/packlets/invitations/invitation-protocol.d.ts +5 -1
  66. package/dist/types/src/packlets/invitations/invitation-protocol.d.ts.map +1 -1
  67. package/dist/types/src/packlets/invitations/invitation-state.d.ts.map +1 -1
  68. package/dist/types/src/packlets/invitations/invitation-topology.d.ts.map +1 -1
  69. package/dist/types/src/packlets/invitations/invitations-handler.d.ts.map +1 -1
  70. package/dist/types/src/packlets/invitations/invitations-manager.d.ts +3 -3
  71. package/dist/types/src/packlets/invitations/invitations-manager.d.ts.map +1 -1
  72. package/dist/types/src/packlets/invitations/invitations-service.d.ts +3 -3
  73. package/dist/types/src/packlets/invitations/invitations-service.d.ts.map +1 -1
  74. package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts +2 -1
  75. package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts.map +1 -1
  76. package/dist/types/src/packlets/invitations/utils.d.ts.map +1 -1
  77. package/dist/types/src/packlets/locks/browser.d.ts.map +1 -1
  78. package/dist/types/src/packlets/locks/node.d.ts.map +1 -1
  79. package/dist/types/src/packlets/logging/logging-service.d.ts.map +1 -1
  80. package/dist/types/src/packlets/network/network-service.d.ts +5 -4
  81. package/dist/types/src/packlets/network/network-service.d.ts.map +1 -1
  82. package/dist/types/src/packlets/services/client-rpc-server.d.ts +3 -3
  83. package/dist/types/src/packlets/services/client-rpc-server.d.ts.map +1 -1
  84. package/dist/types/src/packlets/services/feed-syncer.d.ts +2 -2
  85. package/dist/types/src/packlets/services/feed-syncer.d.ts.map +1 -1
  86. package/dist/types/src/packlets/services/service-context.d.ts +2 -3
  87. package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
  88. package/dist/types/src/packlets/services/service-host.d.ts +2 -3
  89. package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
  90. package/dist/types/src/packlets/services/service-registry.d.ts.map +1 -1
  91. package/dist/types/src/packlets/services/util.d.ts.map +1 -1
  92. package/dist/types/src/packlets/space-export/archive-format.d.ts +9 -0
  93. package/dist/types/src/packlets/space-export/archive-format.d.ts.map +1 -0
  94. package/dist/types/src/packlets/space-export/index.d.ts +4 -1
  95. package/dist/types/src/packlets/space-export/index.d.ts.map +1 -1
  96. package/dist/types/src/packlets/space-export/serialized-space-reader.d.ts +23 -0
  97. package/dist/types/src/packlets/space-export/serialized-space-reader.d.ts.map +1 -0
  98. package/dist/types/src/packlets/space-export/serialized-space-writer.d.ts +36 -0
  99. package/dist/types/src/packlets/space-export/serialized-space-writer.d.ts.map +1 -0
  100. package/dist/types/src/packlets/space-export/space-archive-reader.d.ts +9 -1
  101. package/dist/types/src/packlets/space-export/space-archive-reader.d.ts.map +1 -1
  102. package/dist/types/src/packlets/space-export/space-archive-writer.d.ts +7 -1
  103. package/dist/types/src/packlets/space-export/space-archive-writer.d.ts.map +1 -1
  104. package/dist/types/src/packlets/space-export/space-archive.test.d.ts +2 -0
  105. package/dist/types/src/packlets/space-export/space-archive.test.d.ts.map +1 -0
  106. package/dist/types/src/packlets/spaces/automerge-space-state.d.ts.map +1 -1
  107. package/dist/types/src/packlets/spaces/data-space-manager.d.ts +18 -12
  108. package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
  109. package/dist/types/src/packlets/spaces/data-space.d.ts +24 -7
  110. package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
  111. package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts.map +1 -1
  112. package/dist/types/src/packlets/spaces/epoch-migrations.d.ts.map +1 -1
  113. package/dist/types/src/packlets/spaces/genesis.d.ts +2 -1
  114. package/dist/types/src/packlets/spaces/genesis.d.ts.map +1 -1
  115. package/dist/types/src/packlets/spaces/notarization-plugin.d.ts +1 -4
  116. package/dist/types/src/packlets/spaces/notarization-plugin.d.ts.map +1 -1
  117. package/dist/types/src/packlets/spaces/spaces-service.d.ts +10 -7
  118. package/dist/types/src/packlets/spaces/spaces-service.d.ts.map +1 -1
  119. package/dist/types/src/packlets/storage/level.d.ts.map +1 -1
  120. package/dist/types/src/packlets/storage/profile-archive.d.ts.map +1 -1
  121. package/dist/types/src/packlets/storage/storage.d.ts.map +1 -1
  122. package/dist/types/src/packlets/storage/util.d.ts.map +1 -1
  123. package/dist/types/src/packlets/system/system-service.d.ts +1 -1
  124. package/dist/types/src/packlets/system/system-service.d.ts.map +1 -1
  125. package/dist/types/src/packlets/testing/credential-utils.d.ts.map +1 -1
  126. package/dist/types/src/packlets/testing/invitation-utils.d.ts.map +1 -1
  127. package/dist/types/src/packlets/testing/test-builder.d.ts.map +1 -1
  128. package/dist/types/src/packlets/worker/worker-runtime.d.ts +11 -1
  129. package/dist/types/src/packlets/worker/worker-runtime.d.ts.map +1 -1
  130. package/dist/types/src/packlets/worker/worker-session.d.ts +0 -2
  131. package/dist/types/src/packlets/worker/worker-session.d.ts.map +1 -1
  132. package/dist/types/src/testing/setup.d.ts.map +1 -1
  133. package/dist/types/src/version.d.ts +1 -1
  134. package/dist/types/tsconfig.tsbuildinfo +1 -1
  135. package/package.json +42 -49
  136. package/src/index.ts +1 -0
  137. package/src/packlets/agents/edge-agent-manager.ts +8 -5
  138. package/src/packlets/agents/edge-agent-service.ts +4 -2
  139. package/src/packlets/devices/devices-service.test.ts +0 -1
  140. package/src/packlets/devtools/devtools.ts +0 -1
  141. package/src/packlets/diagnostics/diagnostics.ts +1 -2
  142. package/src/packlets/identity/contacts-service.ts +0 -1
  143. package/src/packlets/identity/identity-manager.test.ts +5 -5
  144. package/src/packlets/identity/identity-manager.ts +18 -17
  145. package/src/packlets/identity/identity-recovery-manager.ts +20 -16
  146. package/src/packlets/identity/identity-service.test.ts +6 -27
  147. package/src/packlets/identity/identity-service.ts +13 -81
  148. package/src/packlets/identity/identity.test.ts +2 -2
  149. package/src/packlets/identity/identity.ts +9 -32
  150. package/src/packlets/invitations/device-invitation-protocol.ts +3 -2
  151. package/src/packlets/invitations/edge-invitation-handler.ts +9 -5
  152. package/src/packlets/invitations/invitation-host-extension.ts +7 -10
  153. package/src/packlets/invitations/invitation-protocol.ts +5 -1
  154. package/src/packlets/invitations/invitation-state.ts +1 -15
  155. package/src/packlets/invitations/invitations-handler.test.ts +4 -5
  156. package/src/packlets/invitations/invitations-handler.ts +67 -15
  157. package/src/packlets/invitations/invitations-manager.ts +40 -15
  158. package/src/packlets/invitations/invitations-service.ts +9 -9
  159. package/src/packlets/invitations/space-invitation-protocol.test.ts +17 -16
  160. package/src/packlets/invitations/space-invitation-protocol.ts +4 -3
  161. package/src/packlets/logging/logging-service.ts +15 -15
  162. package/src/packlets/network/network-service.test.ts +0 -1
  163. package/src/packlets/network/network-service.ts +10 -8
  164. package/src/packlets/services/client-rpc-server.ts +15 -12
  165. package/src/packlets/services/feed-syncer.test.ts +3 -3
  166. package/src/packlets/services/feed-syncer.ts +24 -17
  167. package/src/packlets/services/service-context.test.ts +3 -2
  168. package/src/packlets/services/service-context.ts +91 -40
  169. package/src/packlets/services/service-host.test.ts +8 -8
  170. package/src/packlets/services/service-host.ts +17 -24
  171. package/src/packlets/services/service-registry.test.ts +0 -1
  172. package/src/packlets/space-export/archive-format.ts +42 -0
  173. package/src/packlets/space-export/index.ts +4 -1
  174. package/src/packlets/space-export/serialized-space-reader.ts +111 -0
  175. package/src/packlets/space-export/serialized-space-writer.ts +252 -0
  176. package/src/packlets/space-export/space-archive-reader.ts +64 -3
  177. package/src/packlets/space-export/space-archive-writer.ts +38 -2
  178. package/src/packlets/space-export/space-archive.test.ts +461 -0
  179. package/src/packlets/spaces/data-space-manager.test.ts +79 -13
  180. package/src/packlets/spaces/data-space-manager.ts +75 -111
  181. package/src/packlets/spaces/data-space.ts +49 -29
  182. package/src/packlets/spaces/edge-feed-replicator.test.ts +1 -1
  183. package/src/packlets/spaces/edge-feed-replicator.ts +9 -7
  184. package/src/packlets/spaces/epoch-migrations.ts +3 -3
  185. package/src/packlets/spaces/genesis.ts +6 -1
  186. package/src/packlets/spaces/notarization-plugin.ts +2 -1
  187. package/src/packlets/spaces/spaces-service.test.ts +18 -11
  188. package/src/packlets/spaces/spaces-service.ts +113 -17
  189. package/src/packlets/testing/invitation-utils.ts +3 -2
  190. package/src/packlets/worker/worker-runtime.ts +39 -6
  191. package/src/packlets/worker/worker-session.ts +4 -10
  192. package/src/version.ts +1 -1
  193. package/dist/lib/browser/chunk-MQ6PWJ76.mjs.map +0 -7
  194. package/dist/lib/node-esm/chunk-GUAL4U7S.mjs.map +0 -7
  195. package/dist/types/src/packlets/identity/default-space-state-machine.d.ts +0 -19
  196. package/dist/types/src/packlets/identity/default-space-state-machine.d.ts.map +0 -1
  197. package/src/packlets/identity/default-space-state-machine.ts +0 -44
  198. /package/dist/lib/browser/{chunk-NQSC7HOE.mjs.map → chunk-XJRPB3GA.mjs.map} +0 -0
  199. /package/dist/lib/node-esm/{chunk-PKEGMOQ4.mjs.map → chunk-2DT3MZRL.mjs.map} +0 -0
@@ -3,7 +3,7 @@
3
3
  //
4
4
 
5
5
  import { type ClientServices } from '@dxos/client-protocol';
6
- import { type Any, type ServiceHandler, Stream } from '@dxos/codec-protobuf';
6
+ import { type Any, type RequestOptions, type ServiceHandler, Stream } from '@dxos/codec-protobuf';
7
7
  import { raise } from '@dxos/debug';
8
8
  import { RpcPeer, type RpcPeerOptions, type ServiceBundle, parseMethodName } from '@dxos/rpc';
9
9
  import { MapCounter, trace } from '@dxos/tracing';
@@ -16,12 +16,14 @@ export type ClientRpcServerProps = {
16
16
  handleCall?: (
17
17
  method: string,
18
18
  params: Any,
19
- handler: (method: string, params: Any) => MaybePromise<Any>,
19
+ handler: (method: string, params: Any, options?: RequestOptions) => MaybePromise<Any>,
20
+ options?: RequestOptions,
20
21
  ) => Promise<Any>;
21
22
  handleStream?: (
22
23
  method: string,
23
24
  params: Any,
24
- handler: (method: string, params: Any) => Stream<Any>,
25
+ handler: (method: string, params: Any, options?: RequestOptions) => Stream<Any>,
26
+ options?: RequestOptions,
25
27
  ) => MaybePromise<Stream<Any>>;
26
28
  } & Omit<RpcPeerOptions, 'callHandler' | 'streamHandler'>;
27
29
 
@@ -49,32 +51,33 @@ export class ClientRpcServer {
49
51
  this._serviceRegistry = serviceRegistry;
50
52
  this._rpcPeer = new RpcPeer({
51
53
  ...rpcOptions,
52
- callHandler: (method, params) => {
54
+ callHandler: (method, params, options) => {
53
55
  const [serviceName, methodName] = parseMethodName(method);
54
- const handler = (method: string, params: Any) => this._getServiceHandler(serviceName).call(method, params);
56
+ const handler = (method: string, params: Any, handlerOptions?: RequestOptions) =>
57
+ this._getServiceHandler(serviceName).call(method, params, handlerOptions);
55
58
 
56
59
  this._callMetrics.inc(`${serviceName}.${methodName} request`);
57
60
 
58
61
  if (this._handleCall) {
59
- return this._handleCall(methodName, params, handler);
62
+ return this._handleCall(methodName, params, handler, options);
60
63
  } else {
61
- return handler(methodName, params);
64
+ return handler(methodName, params, options);
62
65
  }
63
66
  },
64
- streamHandler: (method, params) => {
67
+ streamHandler: (method, params, options) => {
65
68
  const [serviceName, methodName] = parseMethodName(method);
66
- const handler = (method: string, params: Any) =>
67
- this._getServiceHandler(serviceName).callStream(method, params);
69
+ const handler = (method: string, params: Any, handlerOptions?: RequestOptions) =>
70
+ this._getServiceHandler(serviceName).callStream(method, params, handlerOptions);
68
71
 
69
72
  this._callMetrics.inc(`${serviceName}.${methodName} request stream`);
70
73
 
71
74
  if (this._handleStream) {
72
- return Stream.map(Stream.unwrapPromise(this._handleStream(methodName, params, handler)), (data) => {
75
+ return Stream.map(Stream.unwrapPromise(this._handleStream(methodName, params, handler, options)), (data) => {
73
76
  this._callMetrics.inc(`${serviceName}.${methodName} response stream`);
74
77
  return data;
75
78
  });
76
79
  } else {
77
- return handler(methodName, params);
80
+ return handler(methodName, params, options);
78
81
  }
79
82
  },
80
83
  });
@@ -69,9 +69,9 @@ const createEdgeConnection = ({
69
69
  setIdentity: () => {},
70
70
  open: async () => {},
71
71
  close: async () => {},
72
- send: async (routerMessage: RouterMessage) => {
72
+ send: async (ctx, routerMessage: RouterMessage) => {
73
73
  const decoded = cborDecode(routerMessage.payload!.value) as ProtocolMessage;
74
- await syncServer.handleMessage(decoded).pipe(RuntimeProvider.runPromise(serverRuntime.runtimeEffect));
74
+ await syncServer.handleMessage(ctx, decoded).pipe(RuntimeProvider.runPromise(serverRuntime.runtimeEffect));
75
75
  },
76
76
  onMessage: (listener: (message: RouterMessage) => void) => {
77
77
  messageListeners.add(listener);
@@ -105,7 +105,7 @@ const createFeedSyncHarness = async ({
105
105
  const syncServer = new SyncServer({
106
106
  peerId: 'server',
107
107
  feedStore: serverFeedStore,
108
- sendMessage: (message) =>
108
+ sendMessage: (_ctx, message) =>
109
109
  Effect.promise(async () => {
110
110
  const routerMessage = createBuf(MessageSchema, {
111
111
  source: {
@@ -8,7 +8,7 @@ import * as Effect from 'effect/Effect';
8
8
  import * as Schema from 'effect/Schema';
9
9
 
10
10
  import { AsyncTask, scheduleTask } from '@dxos/async';
11
- import { Resource } from '@dxos/context';
11
+ import { Context, Resource } from '@dxos/context';
12
12
  import { type EdgeConnection, MessageSchema } from '@dxos/edge-client';
13
13
  import { RuntimeProvider } from '@dxos/effect';
14
14
  import { type FeedStore, SyncClient } from '@dxos/feed';
@@ -176,17 +176,20 @@ export class FeedSyncer extends Resource {
176
176
  /**
177
177
  * Performs queue sync and blocks until there are no pending sync batches.
178
178
  */
179
- async syncBlocking({
180
- spaceId,
181
- subspaceTag,
182
- shouldPush = true,
183
- shouldPull = true,
184
- }: {
185
- spaceId: SpaceId;
186
- subspaceTag: string;
187
- shouldPush?: boolean;
188
- shouldPull?: boolean;
189
- }): Promise<void> {
179
+ async syncBlocking(
180
+ ctx: Context,
181
+ {
182
+ spaceId,
183
+ subspaceTag,
184
+ shouldPush = true,
185
+ shouldPull = true,
186
+ }: {
187
+ spaceId: SpaceId;
188
+ subspaceTag: string;
189
+ shouldPush?: boolean;
190
+ shouldPull?: boolean;
191
+ },
192
+ ): Promise<void> {
190
193
  invariant(SpaceId.isValid(spaceId));
191
194
  invariant(FeedProtocol.isWellKnownNamespace(subspaceTag));
192
195
  if (!shouldPush && !shouldPull) {
@@ -200,7 +203,7 @@ export class FeedSyncer extends Resource {
200
203
  while (!done) {
201
204
  done = true;
202
205
  if (shouldPull) {
203
- const pullResult = yield* this.#syncClient.pull({
206
+ const pullResult = yield* this.#syncClient.pull(ctx, {
204
207
  spaceId,
205
208
  feedNamespace: subspaceTag,
206
209
  limit: this.#messageBlocksLimit,
@@ -209,7 +212,7 @@ export class FeedSyncer extends Resource {
209
212
  }
210
213
 
211
214
  if (shouldPush) {
212
- const pushResult = yield* this.#syncClient.push({
215
+ const pushResult = yield* this.#syncClient.push(ctx, {
213
216
  spaceId,
214
217
  feedNamespace: subspaceTag,
215
218
  limit: this.#messageBlocksLimit,
@@ -233,11 +236,15 @@ export class FeedSyncer extends Resource {
233
236
  this.#lastFullPoll = Date.now();
234
237
  }
235
238
 
236
- #sendMessage(message: FeedProtocol.QueryRequest | FeedProtocol.AppendRequest): Effect.Effect<void, unknown, never> {
239
+ #sendMessage(
240
+ ctx: Context,
241
+ message: FeedProtocol.QueryRequest | FeedProtocol.AppendRequest,
242
+ ): Effect.Effect<void, unknown, never> {
237
243
  return Effect.gen(this, function* () {
238
244
  const encoded = encoder.encode(message);
239
245
  yield* Effect.tryPromise(async () =>
240
246
  this.#edgeClient.send(
247
+ ctx,
241
248
  createBuf(MessageSchema, {
242
249
  source: {
243
250
  identityKey: this.#edgeClient.identityKey,
@@ -266,7 +273,7 @@ export class FeedSyncer extends Resource {
266
273
  Effect.gen(this, function* () {
267
274
  let doneForAllNamespaces = true;
268
275
  for (const feedNamespace of this.#syncNamespaces) {
269
- const { done } = yield* this.#syncClient.pull({
276
+ const { done } = yield* this.#syncClient.pull(this._ctx, {
270
277
  spaceId,
271
278
  feedNamespace,
272
279
  limit: this.#messageBlocksLimit,
@@ -309,7 +316,7 @@ export class FeedSyncer extends Resource {
309
316
  Effect.gen(this, function* () {
310
317
  let doneForAllNamespaces = true;
311
318
  for (const feedNamespace of this.#syncNamespaces) {
312
- const { done } = yield* this.#syncClient.push({
319
+ const { done } = yield* this.#syncClient.push(this._ctx, {
313
320
  spaceId,
314
321
  feedNamespace,
315
322
  limit: this.#messageBlocksLimit,
@@ -4,6 +4,7 @@
4
4
 
5
5
  import { describe, test } from 'vitest';
6
6
 
7
+ import { Context } from '@dxos/context';
7
8
  import { MemorySignalManager, MemorySignalManagerContext } from '@dxos/messaging';
8
9
  import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
9
10
  import { openAndClose } from '@dxos/test-utils';
@@ -19,7 +20,7 @@ describe('services/ServiceContext', () => {
19
20
  const device2 = await createOpenServiceContext(networkContext);
20
21
  await Promise.all(performInvitation({ host: device1, guest: device2, options: { kind: Invitation.Kind.DEVICE } }));
21
22
 
22
- const space1 = await device1.dataSpaceManager!.createSpace();
23
+ const space1 = await device1.dataSpaceManager!.createSpace(new Context());
23
24
  await device2.dataSpaceManager!.waitUntilSpaceReady(space1!.key);
24
25
  const space2 = await device2.dataSpaceManager!.spaces.get(space1.key);
25
26
  await space2!.inner.controlPipeline.state.waitUntilTimeframe(space1.inner.controlPipeline.state.timeframe);
@@ -35,7 +36,7 @@ describe('services/ServiceContext', () => {
35
36
 
36
37
  const identity2 = await createOpenServiceContext(networkContext);
37
38
  await identity2.createIdentity();
38
- const space1 = await identity2.dataSpaceManager!.createSpace();
39
+ const space1 = await identity2.dataSpaceManager!.createSpace(new Context());
39
40
  await Promise.all(
40
41
  performInvitation({
41
42
  host: identity2,
@@ -22,12 +22,12 @@ import { type RuntimeProvider } from '@dxos/effect';
22
22
  import { FeedFactory, FeedStore } from '@dxos/feed-store';
23
23
  import { invariant } from '@dxos/invariant';
24
24
  import { Keyring } from '@dxos/keyring';
25
- import { PublicKey, type SpaceId } from '@dxos/keys';
25
+ import { type SpaceId } from '@dxos/keys';
26
26
  import { type LevelDB } from '@dxos/kv-store';
27
27
  import { log } from '@dxos/log';
28
28
  import { type SignalManager } from '@dxos/messaging';
29
29
  import { type SwarmNetworkManager } from '@dxos/network-manager';
30
- import { InvalidStorageVersionError, STORAGE_VERSION, trace } from '@dxos/protocols';
30
+ import { InvalidStorageVersionError, STORAGE_VERSION } from '@dxos/protocols';
31
31
  import { FeedProtocol } from '@dxos/protocols';
32
32
  import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
33
33
  import { type Runtime } from '@dxos/protocols/proto/dxos/config';
@@ -42,6 +42,7 @@ import { safeInstanceof } from '@dxos/util';
42
42
  import { EdgeAgentManager } from '../agents';
43
43
  import {
44
44
  type CreateIdentityOptions,
45
+ type Identity,
45
46
  IdentityManager,
46
47
  type IdentityManagerProps,
47
48
  type JoinIdentityProps,
@@ -56,7 +57,6 @@ import {
56
57
  SpaceInvitationProtocol,
57
58
  } from '../invitations';
58
59
  import { DataSpaceManager, type DataSpaceManagerRuntimeProps, type SigningContext } from '../spaces';
59
-
60
60
  import { FeedSyncer } from './feed-syncer';
61
61
 
62
62
  export type ServiceContextRuntimeProps = Pick<
@@ -74,7 +74,7 @@ export type ServiceContextRuntimeProps = Pick<
74
74
  // TODO(burdon): Rename/break-up into smaller components. And/or make members private.
75
75
  // TODO(dmaretskyi): Gets duplicated in CJS build between normal and testing bundles.
76
76
  @safeInstanceof('dxos.client-services.ServiceContext')
77
- @Trace.resource()
77
+ @Trace.resource({ lifecycle: true })
78
78
  export class ServiceContext extends Resource {
79
79
  private readonly _edgeIdentityUpdateMutex = new Mutex();
80
80
 
@@ -104,8 +104,6 @@ export class ServiceContext extends Resource {
104
104
 
105
105
  private _deviceSpaceSync?: CredentialProcessor;
106
106
 
107
- private readonly _instanceId = PublicKey.random().toHex();
108
-
109
107
  constructor(
110
108
  public readonly storage: Storage,
111
109
  public readonly level: LevelDB,
@@ -169,8 +167,9 @@ export class ServiceContext extends Resource {
169
167
  peerIdProvider: () => this.identityManager.identity?.deviceKey?.toHex(),
170
168
  getSpaceKeyByRootDocumentId: (documentId) => this.spaceManager.findSpaceByRootDocumentId(documentId)?.key,
171
169
  runtime: this._runtime,
172
- syncQueue: async (request) => {
173
- return this._feedSyncer?.syncBlocking({
170
+ useSubduction: this._edgeFeatures?.subductionReplicator,
171
+ syncQueue: async (ctx, request) => {
172
+ return this._feedSyncer?.syncBlocking(ctx, {
174
173
  spaceId: request.spaceId as SpaceId,
175
174
  subspaceTag: request.subspaceTag,
176
175
  shouldPush: request.shouldPush,
@@ -224,44 +223,75 @@ export class ServiceContext extends Resource {
224
223
  }
225
224
  }
226
225
 
227
- @Trace.span()
226
+ @Trace.span({ op: 'lifecycle' })
228
227
  protected override async _open(ctx: Context): Promise<void> {
229
228
  await this._checkStorageVersion();
230
229
 
231
230
  log('opening...');
232
- log.trace('dxos.sdk.service-context.open', trace.begin({ id: this._instanceId }));
233
231
 
232
+ log('opening identityManager...');
234
233
  await this.identityManager.open(ctx);
234
+ log('identityManager opened', { hasIdentity: !!this.identityManager.identity });
235
+
236
+ log('setting network identity...');
237
+ await this._setNetworkIdentity({ identity: this.identityManager.identity });
238
+ log('network identity set');
239
+
240
+ log('opening edge connection...');
241
+ await this._edgeConnection?.open(ctx);
242
+ log('edge connection opened');
235
243
 
236
- await this._setNetworkIdentity();
244
+ log('opening signal manager...');
245
+ await this.signalManager.open(ctx);
246
+ log('signal manager opened');
237
247
 
238
- await this._edgeConnection?.open();
239
- await this.signalManager.open();
248
+ log('opening network manager...');
240
249
  await this.networkManager.open();
250
+ log('network manager opened');
241
251
 
252
+ log('opening echo host...');
242
253
  await this.echoHost.open(ctx);
254
+ log('echo host opened');
243
255
 
244
256
  if (this._meshReplicator) {
245
- await this.echoHost.addReplicator(this._meshReplicator);
257
+ log('adding mesh replicator...');
258
+ await this.echoHost.addReplicator(ctx, this._meshReplicator);
259
+ log('mesh replicator added');
246
260
  }
247
261
  if (this._echoEdgeReplicator) {
248
- await this.echoHost.addReplicator(this._echoEdgeReplicator);
262
+ log('adding edge replicator...');
263
+ await this.echoHost.addReplicator(ctx, this._echoEdgeReplicator);
264
+ log('edge replicator added');
249
265
  }
250
266
 
267
+ log('loading metadata store...');
251
268
  await this.metadataStore.load();
269
+ log('metadata store loaded');
270
+
271
+ log('opening space manager...');
252
272
  await this.spaceManager.open();
273
+ log('space manager opened');
253
274
 
254
275
  if (this.identityManager.identity) {
255
- await this.identityManager.identity.joinNetwork();
276
+ log('joining network...');
277
+ await this.identityManager.identity.joinNetwork(ctx);
278
+ log('network joined');
279
+
280
+ log('initializing spaces...(calling _initialize)');
256
281
  await this._initialize(ctx);
282
+ log('spaces initialized');
283
+ } else {
284
+ log('no identity, skipping network join and space initialization');
257
285
  }
258
286
 
259
- await this._feedSyncer?.open();
287
+ log('opening feed syncer...');
288
+ await this._feedSyncer?.open(ctx);
289
+ log('feed syncer opened');
260
290
 
261
- const loadedInvitations = await this.invitationsManager.loadPersistentInvitations();
291
+ log('loading persistent invitations...');
292
+ const loadedInvitations = await this.invitationsManager.loadPersistentInvitations(ctx);
262
293
  log('loaded persistent invitations', { count: loadedInvitations.invitations?.length });
263
294
 
264
- log.trace('dxos.sdk.service-context.open', trace.end({ id: this._instanceId }));
265
295
  log('opened');
266
296
  }
267
297
 
@@ -273,13 +303,13 @@ export class ServiceContext extends Resource {
273
303
  if (this._deviceSpaceSync && this.identityManager.identity) {
274
304
  await this.identityManager.identity.space.spaceState.removeCredentialProcessor(this._deviceSpaceSync);
275
305
  }
276
- await this.dataSpaceManager?.close();
306
+ await this.dataSpaceManager?.close(ctx);
277
307
  await this.edgeAgentManager?.close();
278
- await this.identityManager.close();
308
+ await this.identityManager.close(ctx);
279
309
  await this.spaceManager.close();
280
310
  await this.echoHost.close(ctx);
281
311
 
282
- await this.networkManager.close();
312
+ await this.networkManager.close(ctx);
283
313
  await this.signalManager.close();
284
314
  await this._edgeConnection?.close();
285
315
  await this.feedStore.close();
@@ -288,11 +318,12 @@ export class ServiceContext extends Resource {
288
318
  log('closed');
289
319
  }
290
320
 
291
- async createIdentity(params: CreateIdentityOptions = {}) {
292
- const identity = await this.identityManager.createIdentity(params);
293
- await this._setNetworkIdentity();
294
- await identity.joinNetwork();
295
- await this._initialize(new Context());
321
+ async createIdentity(params: CreateIdentityOptions = {}, ctx?: Context) {
322
+ ctx ??= this._ctx;
323
+ const identity = await this.identityManager.createIdentity(params, ctx);
324
+ await this._setNetworkIdentity({ identity });
325
+ await identity.joinNetwork(ctx);
326
+ await this._initialize(ctx);
296
327
  return identity;
297
328
  }
298
329
 
@@ -316,11 +347,11 @@ export class ServiceContext extends Resource {
316
347
  }
317
348
 
318
349
  private async _acceptIdentity(params: JoinIdentityProps) {
319
- const { identity, identityRecord } = await this.identityManager.prepareIdentity(params);
320
- await this._setNetworkIdentity({ deviceCredential: params.authorizedDeviceCredential! });
321
- await identity.joinNetwork();
350
+ const { identity, identityRecord } = await this.identityManager.prepareIdentity(params, this._ctx);
351
+ await this._setNetworkIdentity({ deviceCredential: params.authorizedDeviceCredential!, identity });
352
+ await identity.joinNetwork(this._ctx);
322
353
  await this.identityManager.acceptIdentity(identity, identityRecord, params.deviceProfile);
323
- await this._initialize(new Context());
354
+ await this._initialize(this._ctx);
324
355
  return identity;
325
356
  }
326
357
 
@@ -335,7 +366,7 @@ export class ServiceContext extends Resource {
335
366
  // Called when identity is created.
336
367
  @Trace.span()
337
368
  private async _initialize(ctx: Context): Promise<void> {
338
- log('initializing spaces...');
369
+ log('_initialize: start');
339
370
  const identity = this.identityManager.identity ?? failUndefined();
340
371
  const signingContext: SigningContext = {
341
372
  credentialSigner: identity.getIdentityCredentialSigner(),
@@ -347,6 +378,7 @@ export class ServiceContext extends Resource {
347
378
  },
348
379
  };
349
380
 
381
+ log('_initialize: creating DataSpaceManager');
350
382
  this.dataSpaceManager = new DataSpaceManager({
351
383
  spaceManager: this.spaceManager,
352
384
  metadataStore: this.metadataStore,
@@ -362,7 +394,9 @@ export class ServiceContext extends Resource {
362
394
  runtimeProps: this._runtimeProps as DataSpaceManagerRuntimeProps,
363
395
  edgeFeatures: this._edgeFeatures,
364
396
  });
365
- await this.dataSpaceManager.open();
397
+ log('_initialize: opening DataSpaceManager...');
398
+ await this.dataSpaceManager.open(ctx);
399
+ log('_initialize: DataSpaceManager opened');
366
400
 
367
401
  this.edgeAgentManager = new EdgeAgentManager(
368
402
  this._edgeFeatures,
@@ -370,13 +404,16 @@ export class ServiceContext extends Resource {
370
404
  this.dataSpaceManager,
371
405
  identity,
372
406
  );
373
- await this.edgeAgentManager.open();
407
+ log('_initialize: opening EdgeAgentManager...');
408
+ await this.edgeAgentManager.open(ctx);
409
+ log('_initialize: EdgeAgentManager opened');
374
410
 
375
411
  this._handlerFactories.set(Invitation.Kind.SPACE, (invitation) => {
376
412
  invariant(this.dataSpaceManager, 'dataSpaceManager not initialized yet');
377
413
  return new SpaceInvitationProtocol(this.dataSpaceManager, signingContext, this.keyring, invitation.spaceKey);
378
414
  });
379
415
  this.initialized.wake();
416
+ log('_initialize: initialized.wake() called');
380
417
 
381
418
  this._deviceSpaceSync = {
382
419
  processCredential: async (credential: Credential) => {
@@ -399,9 +436,10 @@ export class ServiceContext extends Resource {
399
436
 
400
437
  try {
401
438
  log('accepting space recorded in halo', { details: assertion });
402
- await this.dataSpaceManager.acceptSpace({
439
+ await this.dataSpaceManager.acceptSpace(this._ctx, {
403
440
  spaceKey: assertion.spaceKey,
404
441
  genesisFeedKey: assertion.genesisFeedKey,
442
+ tags: assertion.tags,
405
443
  });
406
444
  } catch (err) {
407
445
  log.catch(err);
@@ -412,33 +450,42 @@ export class ServiceContext extends Resource {
412
450
  await identity.space.spaceState.addCredentialProcessor(this._deviceSpaceSync);
413
451
  }
414
452
 
415
- private async _setNetworkIdentity(params?: { deviceCredential: Credential }): Promise<void> {
453
+ private async _setNetworkIdentity(params?: { deviceCredential?: Credential; identity?: Identity }): Promise<void> {
454
+ log('_setNetworkIdentity: acquiring mutex...');
416
455
  using _ = await this._edgeIdentityUpdateMutex.acquire();
456
+ log('_setNetworkIdentity: mutex acquired');
417
457
 
418
458
  let edgeIdentity: EdgeIdentity;
419
- const identity = this.identityManager.identity;
459
+ const identity = params?.identity;
420
460
  if (identity) {
421
- log('setting identity on edge connection', {
461
+ log('_setNetworkIdentity: has identity', {
422
462
  identity: identity.identityKey.toHex(),
423
- swarms: this.networkManager.topics,
463
+ hasDeviceCredential: !!params?.deviceCredential,
424
464
  });
425
465
 
426
466
  if (params?.deviceCredential) {
467
+ log('_setNetworkIdentity: creating chain edge identity with device credential...');
427
468
  edgeIdentity = await createChainEdgeIdentity(
428
469
  identity.signer,
429
470
  identity.identityKey,
430
471
  identity.deviceKey,
431
- params?.deviceCredential && { credential: params.deviceCredential },
472
+ { credential: params.deviceCredential },
432
473
  [], // TODO(dmaretskyi): Service access credentials.
433
474
  );
475
+ log('_setNetworkIdentity: chain edge identity created');
434
476
  } else {
477
+ log('_setNetworkIdentity: waiting for identity.ready()...');
435
478
  // TODO: throw here or from identity if device chain can't be loaded, to avoid indefinite hangup
436
479
  await warnAfterTimeout(10_000, 'Waiting for identity to be ready for edge connection', async () => {
437
480
  await identity.ready();
438
481
  });
482
+ log('_setNetworkIdentity: identity.ready() resolved', {
483
+ hasDeviceCredentialChain: !!identity.deviceCredentialChain,
484
+ });
439
485
 
440
486
  invariant(identity.deviceCredentialChain);
441
487
 
488
+ log('_setNetworkIdentity: creating chain edge identity...');
442
489
  edgeIdentity = await createChainEdgeIdentity(
443
490
  identity.signer,
444
491
  identity.identityKey,
@@ -446,9 +493,12 @@ export class ServiceContext extends Resource {
446
493
  identity.deviceCredentialChain,
447
494
  [], // TODO(dmaretskyi): Service access credentials.
448
495
  );
496
+ log('_setNetworkIdentity: chain edge identity created');
449
497
  }
450
498
  } else {
499
+ log('_setNetworkIdentity: no identity, creating ephemeral edge identity...');
451
500
  edgeIdentity = await createEphemeralEdgeIdentity();
501
+ log('_setNetworkIdentity: ephemeral edge identity created');
452
502
  }
453
503
 
454
504
  this._edgeConnection?.setIdentity(edgeIdentity);
@@ -457,5 +507,6 @@ export class ServiceContext extends Resource {
457
507
  identityKey: edgeIdentity.identityKey,
458
508
  peerKey: edgeIdentity.peerKey,
459
509
  });
510
+ log('_setNetworkIdentity: done');
460
511
  }
461
512
  }
@@ -3,7 +3,6 @@
3
3
  //
4
4
 
5
5
  import { rmSync } from 'node:fs';
6
-
7
6
  import { afterEach, describe, expect, onTestFinished, test } from 'vitest';
8
7
 
9
8
  import { Trigger, asyncTimeout, latch } from '@dxos/async';
@@ -13,6 +12,7 @@ import { verifyPresentation } from '@dxos/credentials';
13
12
  import { type PublicKey } from '@dxos/keys';
14
13
  import { MemorySignalManagerContext } from '@dxos/messaging';
15
14
  import { type Identity } from '@dxos/protocols/proto/dxos/client/services';
15
+ import { MembershipPolicy } from '@dxos/protocols/proto/dxos/halo/credentials';
16
16
  import { type Credential } from '@dxos/protocols/proto/dxos/halo/credentials';
17
17
  import { isNode } from '@dxos/util';
18
18
 
@@ -29,16 +29,16 @@ describe('ClientServicesHost', () => {
29
29
  test('open and close', async () => {
30
30
  const host = createServiceHost(new Config(), new MemorySignalManagerContext());
31
31
  await host.open(new Context());
32
- await host.close();
32
+ await host.close(Context.default());
33
33
  });
34
34
 
35
35
  test('queryCredentials', async () => {
36
36
  const host = createServiceHost(new Config(), new MemorySignalManagerContext());
37
37
  await host.open(new Context());
38
- onTestFinished(() => host.close());
38
+ onTestFinished(() => host.close(Context.default()));
39
39
 
40
40
  await host.services.IdentityService!.createIdentity({});
41
- const { spaceKey } = await host.services.SpacesService!.createSpace();
41
+ const { spaceKey } = await host.services.SpacesService!.createSpace({ membershipPolicy: MembershipPolicy.INVITE });
42
42
 
43
43
  const stream = host.services.SpacesService!.queryCredentials({ spaceKey });
44
44
  const [done, tick] = latch({ count: 3 });
@@ -54,7 +54,7 @@ describe('ClientServicesHost', () => {
54
54
  test('write and query credentials', async () => {
55
55
  const host = createServiceHost(new Config(), new MemorySignalManagerContext());
56
56
  await host.open(new Context());
57
- onTestFinished(() => host.close());
57
+ onTestFinished(() => host.close(Context.default()));
58
58
 
59
59
  await host.services.IdentityService!.createIdentity({});
60
60
 
@@ -91,7 +91,7 @@ describe('ClientServicesHost', () => {
91
91
  test('sign presentation', async () => {
92
92
  const host = createServiceHost(new Config(), new MemorySignalManagerContext());
93
93
  await host.open(new Context());
94
- onTestFinished(() => host.close());
94
+ onTestFinished(() => host.close(Context.default()));
95
95
 
96
96
  await host.services.IdentityService!.createIdentity({});
97
97
 
@@ -128,7 +128,7 @@ describe('ClientServicesHost', () => {
128
128
  expect(host.context.storage.size).to.exist;
129
129
 
130
130
  await asyncTimeout(host.reset(), 1000);
131
- await host.close();
131
+ await host.close(Context.default());
132
132
  }
133
133
 
134
134
  {
@@ -146,7 +146,7 @@ describe('ClientServicesHost', () => {
146
146
  });
147
147
  await expect(asyncTimeout(trigger.wait(), 200)).rejects.toBeInstanceOf(Error);
148
148
  await stream?.close();
149
- await host.close();
149
+ await host.close(Context.default());
150
150
  }
151
151
  });
152
152
  });