@dxos/client-services 0.8.4-main.9be5663bfe → 0.8.4-main.abd8ff62ef

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. package/dist/lib/browser/{chunk-CK3KJB3B.mjs → chunk-KW4WMU5R.mjs} +1310 -3084
  2. package/dist/lib/browser/chunk-KW4WMU5R.mjs.map +7 -0
  3. package/dist/lib/browser/{chunk-NQSC7HOE.mjs → chunk-XJRPB3GA.mjs} +1 -1
  4. package/dist/lib/browser/index.mjs +100 -197
  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 +7 -27
  15. package/dist/lib/browser/testing/index.mjs.map +2 -2
  16. package/dist/lib/node-esm/{chunk-PKEGMOQ4.mjs → chunk-2DT3MZRL.mjs} +1 -1
  17. package/dist/lib/node-esm/{chunk-WHBWCIEN.mjs → chunk-NDMKP2CH.mjs} +1310 -3084
  18. package/dist/lib/node-esm/chunk-NDMKP2CH.mjs.map +7 -0
  19. package/dist/lib/node-esm/index.mjs +100 -197
  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 +7 -27
  30. package/dist/lib/node-esm/testing/index.mjs.map +2 -2
  31. package/dist/types/src/packlets/agents/edge-agent-manager.d.ts.map +1 -1
  32. package/dist/types/src/packlets/agents/edge-agent-service.d.ts +2 -1
  33. package/dist/types/src/packlets/agents/edge-agent-service.d.ts.map +1 -1
  34. package/dist/types/src/packlets/devices/devices-service.d.ts.map +1 -1
  35. package/dist/types/src/packlets/devtools/devtools.d.ts.map +1 -1
  36. package/dist/types/src/packlets/devtools/feeds.d.ts.map +1 -1
  37. package/dist/types/src/packlets/devtools/keys.d.ts.map +1 -1
  38. package/dist/types/src/packlets/devtools/metadata.d.ts.map +1 -1
  39. package/dist/types/src/packlets/devtools/network.d.ts.map +1 -1
  40. package/dist/types/src/packlets/devtools/spaces.d.ts.map +1 -1
  41. package/dist/types/src/packlets/diagnostics/browser-diagnostics-broadcast.d.ts.map +1 -1
  42. package/dist/types/src/packlets/diagnostics/diagnostics-broadcast.d.ts.map +1 -1
  43. package/dist/types/src/packlets/diagnostics/diagnostics-collector.d.ts.map +1 -1
  44. package/dist/types/src/packlets/diagnostics/diagnostics.d.ts +2 -3
  45. package/dist/types/src/packlets/diagnostics/diagnostics.d.ts.map +1 -1
  46. package/dist/types/src/packlets/identity/authenticator.d.ts.map +1 -1
  47. package/dist/types/src/packlets/identity/contacts-service.d.ts.map +1 -1
  48. package/dist/types/src/packlets/identity/identity-manager.d.ts.map +1 -1
  49. package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts +2 -2
  50. package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts.map +1 -1
  51. package/dist/types/src/packlets/identity/identity-service.d.ts +6 -5
  52. package/dist/types/src/packlets/identity/identity-service.d.ts.map +1 -1
  53. package/dist/types/src/packlets/identity/identity.d.ts.map +1 -1
  54. package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts +2 -1
  55. package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts.map +1 -1
  56. package/dist/types/src/packlets/invitations/edge-invitation-handler.d.ts +1 -1
  57. package/dist/types/src/packlets/invitations/edge-invitation-handler.d.ts.map +1 -1
  58. package/dist/types/src/packlets/invitations/invitation-guest-extenstion.d.ts.map +1 -1
  59. package/dist/types/src/packlets/invitations/invitation-host-extension.d.ts.map +1 -1
  60. package/dist/types/src/packlets/invitations/invitation-protocol.d.ts +5 -1
  61. package/dist/types/src/packlets/invitations/invitation-protocol.d.ts.map +1 -1
  62. package/dist/types/src/packlets/invitations/invitation-state.d.ts.map +1 -1
  63. package/dist/types/src/packlets/invitations/invitation-topology.d.ts.map +1 -1
  64. package/dist/types/src/packlets/invitations/invitations-handler.d.ts.map +1 -1
  65. package/dist/types/src/packlets/invitations/invitations-manager.d.ts +1 -1
  66. package/dist/types/src/packlets/invitations/invitations-manager.d.ts.map +1 -1
  67. package/dist/types/src/packlets/invitations/invitations-service.d.ts +3 -3
  68. package/dist/types/src/packlets/invitations/invitations-service.d.ts.map +1 -1
  69. package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts +2 -1
  70. package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts.map +1 -1
  71. package/dist/types/src/packlets/invitations/utils.d.ts.map +1 -1
  72. package/dist/types/src/packlets/locks/browser.d.ts.map +1 -1
  73. package/dist/types/src/packlets/locks/node.d.ts.map +1 -1
  74. package/dist/types/src/packlets/logging/logging-service.d.ts.map +1 -1
  75. package/dist/types/src/packlets/network/network-service.d.ts +5 -4
  76. package/dist/types/src/packlets/network/network-service.d.ts.map +1 -1
  77. package/dist/types/src/packlets/services/client-rpc-server.d.ts +3 -3
  78. package/dist/types/src/packlets/services/client-rpc-server.d.ts.map +1 -1
  79. package/dist/types/src/packlets/services/feed-syncer.d.ts +1 -1
  80. package/dist/types/src/packlets/services/feed-syncer.d.ts.map +1 -1
  81. package/dist/types/src/packlets/services/service-context.d.ts +1 -2
  82. package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
  83. package/dist/types/src/packlets/services/service-host.d.ts +1 -2
  84. package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
  85. package/dist/types/src/packlets/services/service-registry.d.ts.map +1 -1
  86. package/dist/types/src/packlets/services/util.d.ts.map +1 -1
  87. package/dist/types/src/packlets/space-export/archive-format.d.ts +9 -0
  88. package/dist/types/src/packlets/space-export/archive-format.d.ts.map +1 -0
  89. package/dist/types/src/packlets/space-export/index.d.ts +4 -1
  90. package/dist/types/src/packlets/space-export/index.d.ts.map +1 -1
  91. package/dist/types/src/packlets/space-export/serialized-space-reader.d.ts +23 -0
  92. package/dist/types/src/packlets/space-export/serialized-space-reader.d.ts.map +1 -0
  93. package/dist/types/src/packlets/space-export/serialized-space-writer.d.ts +36 -0
  94. package/dist/types/src/packlets/space-export/serialized-space-writer.d.ts.map +1 -0
  95. package/dist/types/src/packlets/space-export/space-archive-reader.d.ts.map +1 -1
  96. package/dist/types/src/packlets/space-export/space-archive-writer.d.ts +1 -1
  97. package/dist/types/src/packlets/space-export/space-archive-writer.d.ts.map +1 -1
  98. package/dist/types/src/packlets/spaces/automerge-space-state.d.ts.map +1 -1
  99. package/dist/types/src/packlets/spaces/data-space-manager.d.ts +1 -2
  100. package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
  101. package/dist/types/src/packlets/spaces/data-space.d.ts +2 -1
  102. package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
  103. package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts.map +1 -1
  104. package/dist/types/src/packlets/spaces/epoch-migrations.d.ts.map +1 -1
  105. package/dist/types/src/packlets/spaces/genesis.d.ts.map +1 -1
  106. package/dist/types/src/packlets/spaces/notarization-plugin.d.ts +1 -4
  107. package/dist/types/src/packlets/spaces/notarization-plugin.d.ts.map +1 -1
  108. package/dist/types/src/packlets/spaces/spaces-service.d.ts +9 -6
  109. package/dist/types/src/packlets/spaces/spaces-service.d.ts.map +1 -1
  110. package/dist/types/src/packlets/storage/level.d.ts.map +1 -1
  111. package/dist/types/src/packlets/storage/profile-archive.d.ts.map +1 -1
  112. package/dist/types/src/packlets/storage/storage.d.ts.map +1 -1
  113. package/dist/types/src/packlets/storage/util.d.ts.map +1 -1
  114. package/dist/types/src/packlets/system/system-service.d.ts +1 -1
  115. package/dist/types/src/packlets/system/system-service.d.ts.map +1 -1
  116. package/dist/types/src/packlets/testing/credential-utils.d.ts.map +1 -1
  117. package/dist/types/src/packlets/testing/invitation-utils.d.ts.map +1 -1
  118. package/dist/types/src/packlets/testing/test-builder.d.ts.map +1 -1
  119. package/dist/types/src/packlets/worker/worker-runtime.d.ts +11 -1
  120. package/dist/types/src/packlets/worker/worker-runtime.d.ts.map +1 -1
  121. package/dist/types/src/packlets/worker/worker-session.d.ts +0 -2
  122. package/dist/types/src/packlets/worker/worker-session.d.ts.map +1 -1
  123. package/dist/types/src/testing/setup.d.ts.map +1 -1
  124. package/dist/types/src/version.d.ts +1 -1
  125. package/dist/types/tsconfig.tsbuildinfo +1 -1
  126. package/package.json +39 -46
  127. package/src/packlets/agents/edge-agent-service.ts +3 -2
  128. package/src/packlets/diagnostics/diagnostics.ts +1 -2
  129. package/src/packlets/identity/identity-manager.ts +2 -4
  130. package/src/packlets/identity/identity-service.ts +12 -9
  131. package/src/packlets/identity/identity.ts +2 -2
  132. package/src/packlets/invitations/device-invitation-protocol.ts +3 -1
  133. package/src/packlets/invitations/edge-invitation-handler.ts +5 -2
  134. package/src/packlets/invitations/invitation-host-extension.ts +7 -10
  135. package/src/packlets/invitations/invitation-protocol.ts +5 -1
  136. package/src/packlets/invitations/invitation-state.ts +1 -15
  137. package/src/packlets/invitations/invitations-handler.ts +64 -12
  138. package/src/packlets/invitations/invitations-manager.ts +6 -4
  139. package/src/packlets/invitations/invitations-service.ts +6 -6
  140. package/src/packlets/invitations/space-invitation-protocol.ts +3 -3
  141. package/src/packlets/logging/logging-service.ts +15 -15
  142. package/src/packlets/network/network-service.ts +9 -8
  143. package/src/packlets/services/client-rpc-server.ts +15 -12
  144. package/src/packlets/services/service-context.ts +12 -15
  145. package/src/packlets/services/service-host.ts +8 -19
  146. package/src/packlets/space-export/archive-format.ts +42 -0
  147. package/src/packlets/space-export/index.ts +4 -1
  148. package/src/packlets/space-export/serialized-space-reader.ts +111 -0
  149. package/src/packlets/space-export/serialized-space-writer.ts +253 -0
  150. package/src/packlets/space-export/space-archive-writer.ts +2 -1
  151. package/src/packlets/space-export/space-archive.test.ts +175 -1
  152. package/src/packlets/spaces/data-space-manager.ts +17 -19
  153. package/src/packlets/spaces/data-space.ts +9 -7
  154. package/src/packlets/spaces/edge-feed-replicator.ts +1 -0
  155. package/src/packlets/spaces/spaces-service.test.ts +9 -4
  156. package/src/packlets/spaces/spaces-service.ts +91 -16
  157. package/src/packlets/worker/worker-runtime.ts +38 -4
  158. package/src/packlets/worker/worker-session.ts +4 -10
  159. package/src/version.ts +1 -1
  160. package/dist/lib/browser/chunk-CK3KJB3B.mjs.map +0 -7
  161. package/dist/lib/node-esm/chunk-WHBWCIEN.mjs.map +0 -7
  162. /package/dist/lib/browser/{chunk-NQSC7HOE.mjs.map → chunk-XJRPB3GA.mjs.map} +0 -0
  163. /package/dist/lib/node-esm/{chunk-PKEGMOQ4.mjs.map → chunk-2DT3MZRL.mjs.map} +0 -0
@@ -2,7 +2,7 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
- import { Stream } from '@dxos/codec-protobuf/stream';
5
+ import { type RequestOptions, Stream } from '@dxos/codec-protobuf';
6
6
  import {
7
7
  type AcceptInvitationRequest,
8
8
  type AuthenticationRequest,
@@ -27,23 +27,23 @@ export class InvitationsServiceImpl implements InvitationsService {
27
27
  };
28
28
  }
29
29
 
30
- createInvitation(options: Invitation): Stream<Invitation> {
30
+ createInvitation(request: Invitation, options?: RequestOptions): Stream<Invitation> {
31
31
  return new Stream<Invitation>(({ ctx, next, close }) => {
32
32
  void this._invitationsManager
33
- .createInvitation(ctx, options)
33
+ .createInvitation(ctx, request)
34
34
  .then((invitation) => {
35
35
  trace.metrics.increment('dxos.invitation.created');
36
36
  invitation.subscribe(next, close, close);
37
37
  })
38
38
  .catch(close);
39
- });
39
+ }, options?.ctx);
40
40
  }
41
41
 
42
- acceptInvitation(request: AcceptInvitationRequest): Stream<Invitation> {
42
+ acceptInvitation(request: AcceptInvitationRequest, options?: RequestOptions): Stream<Invitation> {
43
43
  return new Stream<Invitation>(({ ctx, next, close }) => {
44
44
  const invitation = this._invitationsManager.acceptInvitation(ctx, request);
45
45
  invitation.subscribe(next, close, close);
46
- });
46
+ }, options?.ctx);
47
47
  }
48
48
 
49
49
  async authenticate(request: AuthenticationRequest): Promise<void> {
@@ -2,7 +2,7 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { Context } from '@dxos/context';
5
+ import { type Context } from '@dxos/context';
6
6
  import {
7
7
  createCancelDelegatedSpaceInvitationCredential,
8
8
  createDelegatedSpaceInvitationCredential,
@@ -170,7 +170,7 @@ export class SpaceInvitationProtocol implements InvitationProtocol {
170
170
  };
171
171
  }
172
172
 
173
- async accept(response: AdmissionResponse): Promise<Partial<Invitation>> {
173
+ async accept(ctx: Context, response: AdmissionResponse): Promise<Partial<Invitation>> {
174
174
  invariant(response.space);
175
175
  const { credential, controlTimeframe, dataTimeframe } = response.space;
176
176
  const assertion = getCredentialAssertion(credential);
@@ -182,7 +182,7 @@ export class SpaceInvitationProtocol implements InvitationProtocol {
182
182
  }
183
183
 
184
184
  // Create local space.
185
- await this._spaceManager.acceptSpace(Context.default(), {
185
+ await this._spaceManager.acceptSpace(ctx, {
186
186
  spaceKey: assertion.spaceKey,
187
187
  genesisFeedKey: assertion.genesisFeedKey,
188
188
  controlTimeframe,
@@ -5,13 +5,7 @@
5
5
  import { Event } from '@dxos/async';
6
6
  import { Stream } from '@dxos/codec-protobuf/stream';
7
7
  import { PublicKey } from '@dxos/keys';
8
- import {
9
- type LogLevel,
10
- type LogProcessor,
11
- type LogEntry as NaturalLogEntry,
12
- getContextFromEntry,
13
- log,
14
- } from '@dxos/log';
8
+ import { type LogLevel, type LogProcessor, type LogEntry as NaturalLogEntry, log } from '@dxos/log';
15
9
  import {
16
10
  type ControlMetricsRequest,
17
11
  type ControlMetricsResponse,
@@ -22,7 +16,7 @@ import {
22
16
  type QueryMetricsRequest,
23
17
  type QueryMetricsResponse,
24
18
  } from '@dxos/protocols/proto/dxos/client/services';
25
- import { getDebugName, jsonify, numericalValues, tracer } from '@dxos/util';
19
+ import { numericalValues, tracer } from '@dxos/util';
26
20
 
27
21
  /**
28
22
  * Logging service used to spy on logs of the host.
@@ -114,19 +108,25 @@ export class LoggingServiceImpl implements LoggingService {
114
108
  return;
115
109
  }
116
110
 
111
+ const { filename, line, context: scopeName } = entry.computedMeta;
112
+ const recordContext: Record<string, any> = { ...entry.computedContext };
113
+ if (entry.computedError !== undefined) {
114
+ recordContext.error = entry.computedError;
115
+ }
116
+
117
117
  const record: LogEntry = {
118
- ...entry,
119
- message: entry.message ?? (entry.error ? (entry.error.message ?? String(entry.error)) : ''),
120
- context: jsonify(getContextFromEntry(entry)),
121
- timestamp: new Date(),
118
+ level: entry.level,
119
+ message: entry.message ?? entry.computedError ?? '',
120
+ context: recordContext,
121
+ timestamp: new Date(entry.timestamp),
122
122
  meta: {
123
123
  // TODO(dmaretskyi): Fix proto.
124
- file: entry.meta?.F ?? '',
125
- line: entry.meta?.L ?? 0,
124
+ file: filename ?? '',
125
+ line: line ?? 0,
126
126
  scope: {
127
127
  hostSessionId: this._sessionId,
128
128
  uptimeSeconds: (Date.now() - this._started) / 1000,
129
- name: getDebugName(entry.meta?.S),
129
+ name: scopeName ?? '',
130
130
  },
131
131
  },
132
132
  };
@@ -2,6 +2,7 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
+ import { type RequestOptions } from '@dxos/codec-protobuf';
5
6
  import { Stream } from '@dxos/codec-protobuf/stream';
6
7
  import { Context } from '@dxos/context';
7
8
  import { type EdgeConnection } from '@dxos/edge-client';
@@ -48,16 +49,16 @@ export class NetworkServiceImpl implements NetworkService {
48
49
  await this.networkManager.setConnectionState(request.swarm);
49
50
  }
50
51
 
51
- async joinSwarm(request: JoinRequest): Promise<void> {
52
- return this.signalManager.join(Context.default(), request);
52
+ async joinSwarm(request: JoinRequest, options?: RequestOptions): Promise<void> {
53
+ return this.signalManager.join(options?.ctx ?? Context.default(), request);
53
54
  }
54
55
 
55
- async leaveSwarm(request: LeaveRequest): Promise<void> {
56
- return this.signalManager.leave(Context.default(), request);
56
+ async leaveSwarm(request: LeaveRequest, options?: RequestOptions): Promise<void> {
57
+ return this.signalManager.leave(options?.ctx ?? Context.default(), request);
57
58
  }
58
59
 
59
- async querySwarm(request: QueryRequest): Promise<SwarmResponse> {
60
- return this.signalManager.query(Context.default(), request);
60
+ async querySwarm(request: QueryRequest, options?: RequestOptions): Promise<SwarmResponse> {
61
+ return this.signalManager.query(options?.ctx ?? Context.default(), request);
61
62
  }
62
63
 
63
64
  subscribeSwarmState(request: SubscribeSwarmStateRequest): Stream<SwarmResponse> {
@@ -70,8 +71,8 @@ export class NetworkServiceImpl implements NetworkService {
70
71
  });
71
72
  }
72
73
 
73
- async sendMessage(message: Message): Promise<void> {
74
- return this.signalManager.sendMessage(Context.default(), message);
74
+ async sendMessage(message: Message, options?: RequestOptions): Promise<void> {
75
+ return this.signalManager.sendMessage(options?.ctx ?? Context.default(), message);
75
76
  }
76
77
 
77
78
  subscribeMessages(peer: Peer): Stream<Message> {
@@ -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
  });
@@ -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';
@@ -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,
@@ -224,12 +222,11 @@ export class ServiceContext extends Resource {
224
222
  }
225
223
  }
226
224
 
227
- @Trace.span()
225
+ @Trace.span({ op: 'lifecycle' })
228
226
  protected override async _open(ctx: Context): Promise<void> {
229
227
  await this._checkStorageVersion();
230
228
 
231
229
  log('opening...');
232
- log.trace('dxos.sdk.service-context.open', trace.begin({ id: this._instanceId }));
233
230
 
234
231
  log('opening identityManager...');
235
232
  await this.identityManager.open(ctx);
@@ -240,11 +237,11 @@ export class ServiceContext extends Resource {
240
237
  log('network identity set');
241
238
 
242
239
  log('opening edge connection...');
243
- await this._edgeConnection?.open();
240
+ await this._edgeConnection?.open(ctx);
244
241
  log('edge connection opened');
245
242
 
246
243
  log('opening signal manager...');
247
- await this.signalManager.open();
244
+ await this.signalManager.open(ctx);
248
245
  log('signal manager opened');
249
246
 
250
247
  log('opening network manager...');
@@ -287,14 +284,13 @@ export class ServiceContext extends Resource {
287
284
  }
288
285
 
289
286
  log('opening feed syncer...');
290
- await this._feedSyncer?.open();
287
+ await this._feedSyncer?.open(ctx);
291
288
  log('feed syncer opened');
292
289
 
293
290
  log('loading persistent invitations...');
294
291
  const loadedInvitations = await this.invitationsManager.loadPersistentInvitations(ctx);
295
292
  log('loaded persistent invitations', { count: loadedInvitations.invitations?.length });
296
293
 
297
- log.trace('dxos.sdk.service-context.open', trace.end({ id: this._instanceId }));
298
294
  log('opened');
299
295
  }
300
296
 
@@ -321,8 +317,8 @@ export class ServiceContext extends Resource {
321
317
  log('closed');
322
318
  }
323
319
 
324
- async createIdentity(params: CreateIdentityOptions = {}) {
325
- const ctx = Context.default();
320
+ async createIdentity(params: CreateIdentityOptions = {}, ctx?: Context) {
321
+ ctx ??= this._ctx;
326
322
  const identity = await this.identityManager.createIdentity(params, ctx);
327
323
  await this._setNetworkIdentity({ identity });
328
324
  await identity.joinNetwork(ctx);
@@ -398,7 +394,7 @@ export class ServiceContext extends Resource {
398
394
  edgeFeatures: this._edgeFeatures,
399
395
  });
400
396
  log('_initialize: opening DataSpaceManager...');
401
- await this.dataSpaceManager.open();
397
+ await this.dataSpaceManager.open(ctx);
402
398
  log('_initialize: DataSpaceManager opened');
403
399
 
404
400
  this.edgeAgentManager = new EdgeAgentManager(
@@ -408,7 +404,7 @@ export class ServiceContext extends Resource {
408
404
  identity,
409
405
  );
410
406
  log('_initialize: opening EdgeAgentManager...');
411
- await this.edgeAgentManager.open();
407
+ await this.edgeAgentManager.open(ctx);
412
408
  log('_initialize: EdgeAgentManager opened');
413
409
 
414
410
  this._handlerFactories.set(Invitation.Kind.SPACE, (invitation) => {
@@ -442,6 +438,7 @@ export class ServiceContext extends Resource {
442
438
  await this.dataSpaceManager.acceptSpace(this._ctx, {
443
439
  spaceKey: assertion.spaceKey,
444
440
  genesisFeedKey: assertion.genesisFeedKey,
441
+ tags: assertion.tags,
445
442
  });
446
443
  } catch (err) {
447
444
  log.catch(err);
@@ -7,12 +7,11 @@ import * as Effect from 'effect/Effect';
7
7
 
8
8
  import { Event, synchronized } from '@dxos/async';
9
9
  import { type ClientServices, clientServiceBundle } from '@dxos/client-protocol';
10
- import { type Config } from '@dxos/config';
10
+ import { type Config, resolveTelemetryTag } from '@dxos/config';
11
11
  import { Context } from '@dxos/context';
12
12
  import { EdgeClient, type EdgeConnection, EdgeHttpClient, createStubEdgeIdentity } from '@dxos/edge-client';
13
13
  import { RuntimeProvider } from '@dxos/effect';
14
14
  import { invariant } from '@dxos/invariant';
15
- import { PublicKey } from '@dxos/keys';
16
15
  import { type LevelDB } from '@dxos/kv-store';
17
16
  import { log } from '@dxos/log';
18
17
  import { EdgeSignalManager, type SignalManager, WebsocketSignalManager } from '@dxos/messaging';
@@ -22,12 +21,11 @@ import {
22
21
  createIceProvider,
23
22
  createRtcTransportFactory,
24
23
  } from '@dxos/network-manager';
25
- import { trace } from '@dxos/protocols';
26
24
  import { SystemStatus } from '@dxos/protocols/proto/dxos/client/services';
27
25
  import { type Storage } from '@dxos/random-access-storage';
28
26
  import * as SqlExport from '@dxos/sql-sqlite/SqlExport';
29
27
  import type * as SqlTransaction from '@dxos/sql-sqlite/SqlTransaction';
30
- import { TRACE_PROCESSOR, trace as Trace } from '@dxos/tracing';
28
+ import { trace as Trace } from '@dxos/tracing';
31
29
  import { WebsocketRpcClient } from '@dxos/websocket-rpc';
32
30
 
33
31
  import { EdgeAgentServiceImpl } from '../agents';
@@ -86,8 +84,6 @@ export class ClientServicesHost {
86
84
  private readonly _serviceRegistry: ServiceRegistry<ClientServices>;
87
85
  private readonly _systemService: SystemServiceImpl;
88
86
  private readonly _loggingService: LoggingServiceImpl;
89
- private readonly _tracingService = TRACE_PROCESSOR.createTraceSender();
90
-
91
87
  private readonly _statusUpdate = new Event<void>();
92
88
 
93
89
  private _config?: Config;
@@ -175,7 +171,6 @@ export class ClientServicesHost {
175
171
 
176
172
  this._serviceRegistry = new ServiceRegistry<ClientServices>(clientServiceBundle, {
177
173
  SystemService: this._systemService,
178
- TracingService: this._tracingService,
179
174
  });
180
175
  }
181
176
 
@@ -258,7 +253,7 @@ export class ClientServicesHost {
258
253
 
259
254
  const endpoint = config?.get('runtime.services.edge.url');
260
255
  if (endpoint) {
261
- const clientTag = config?.get('runtime.app.env.DX_EDGE_CLIENT_TAG');
256
+ const clientTag = resolveTelemetryTag(config);
262
257
  this._edgeConnection = new EdgeClient(createStubEdgeIdentity(), { socketEndpoint: endpoint, clientTag });
263
258
  this._edgeHttpClient = new EdgeHttpClient(endpoint, { clientTag });
264
259
  }
@@ -299,8 +294,7 @@ export class ClientServicesHost {
299
294
  return;
300
295
  }
301
296
 
302
- const traceId = PublicKey.random().toHex();
303
- log.trace('dxos.client-services.host.open', trace.begin({ id: traceId }));
297
+ log('opening service host');
304
298
 
305
299
  invariant(this._config, 'config not set');
306
300
  invariant(this._storage, 'storage not set');
@@ -345,7 +339,7 @@ export class ClientServicesHost {
345
339
  this._serviceContext.identityManager,
346
340
  this._serviceContext.recoveryManager,
347
341
  this._serviceContext.keyring,
348
- (params) => this._createIdentity(params),
342
+ (params, ctx) => this._createIdentity(params, ctx),
349
343
  (profile) => this._serviceContext.broadcastProfileUpdate(profile),
350
344
  );
351
345
 
@@ -365,6 +359,7 @@ export class ClientServicesHost {
365
359
  SpacesService: new SpacesServiceImpl(
366
360
  this._serviceContext.identityManager,
367
361
  this._serviceContext.spaceManager,
362
+ this._serviceContext.echoHost,
368
363
  dataSpaceManagerProvider,
369
364
  ),
370
365
 
@@ -379,7 +374,6 @@ export class ClientServicesHost {
379
374
  ),
380
375
 
381
376
  LoggingService: this._loggingService,
382
- TracingService: this._tracingService,
383
377
 
384
378
  // TODO(burdon): Move to new protobuf definitions.
385
379
  DevtoolsHost: new DevtoolsServiceImpl({
@@ -416,7 +410,6 @@ export class ClientServicesHost {
416
410
  this._statusUpdate.emit();
417
411
  const deviceKey = this._serviceContext.identityManager.identity?.deviceKey;
418
412
  log('opened', { deviceKey });
419
- log.trace('dxos.client-services.host.open', trace.end({ id: traceId }));
420
413
  }
421
414
 
422
415
  @synchronized
@@ -440,9 +433,6 @@ export class ClientServicesHost {
440
433
  }
441
434
 
442
435
  async reset(): Promise<void> {
443
- const traceId = PublicKey.random().toHex();
444
- log.trace('dxos.sdk.client-services-host.reset', trace.begin({ id: traceId }));
445
-
446
436
  log.info('resetting...');
447
437
  // Emit this status update immediately so app returns to fallback.
448
438
  // This state is never cleared because the app reloads.
@@ -457,12 +447,11 @@ export class ClientServicesHost {
457
447
  }
458
448
  await this._storage!.reset();
459
449
  log.info('reset');
460
- log.trace('dxos.sdk.client-services-host.reset', trace.end({ id: traceId }));
461
450
  await this._callbacks?.onReset?.();
462
451
  }
463
452
 
464
- private async _createIdentity(params: CreateIdentityOptions) {
465
- const identity = await this._serviceContext.createIdentity(params);
453
+ private async _createIdentity(params: CreateIdentityOptions, ctx?: Context) {
454
+ const identity = await this._serviceContext.createIdentity(params, ctx);
466
455
  await this._serviceContext.initialized.wait();
467
456
  return identity;
468
457
  }
@@ -0,0 +1,42 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { SpaceArchive } from '@dxos/protocols/proto/dxos/client/services';
6
+
7
+ const JSON_EXTENSIONS = ['.dx.json', '.dx.json.gz', '.json'];
8
+ const BINARY_EXTENSIONS = ['.tar', '.tar.gz'];
9
+
10
+ /**
11
+ * Detect the format of a space archive.
12
+ *
13
+ * Uses filename extension as the primary signal, and falls back to sniffing
14
+ * the first bytes of the archive contents to distinguish JSON from tar.
15
+ */
16
+ export const detectSpaceArchiveFormat = (archive: Pick<SpaceArchive, 'filename' | 'contents'>): SpaceArchive.Format => {
17
+ const filename = archive.filename?.toLowerCase() ?? '';
18
+ if (JSON_EXTENSIONS.some((ext) => filename.endsWith(ext))) {
19
+ return SpaceArchive.Format.JSON;
20
+ }
21
+ if (BINARY_EXTENSIONS.some((ext) => filename.endsWith(ext))) {
22
+ return SpaceArchive.Format.BINARY;
23
+ }
24
+
25
+ // Fall back to byte sniffing: JSON archives start with '{' (0x7B) or whitespace.
26
+ const bytes = archive.contents;
27
+ if (bytes && bytes.length > 0) {
28
+ for (let i = 0; i < Math.min(bytes.length, 16); i++) {
29
+ const byte = bytes[i];
30
+ // Skip whitespace.
31
+ if (byte === 0x20 || byte === 0x09 || byte === 0x0a || byte === 0x0d) {
32
+ continue;
33
+ }
34
+ if (byte === 0x7b /* '{' */) {
35
+ return SpaceArchive.Format.JSON;
36
+ }
37
+ break;
38
+ }
39
+ }
40
+
41
+ return SpaceArchive.Format.BINARY;
42
+ };
@@ -2,5 +2,8 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- export * from './space-archive-writer';
5
+ export * from './archive-format';
6
+ export * from './serialized-space-reader';
7
+ export * from './serialized-space-writer';
6
8
  export * from './space-archive-reader';
9
+ export * from './space-archive-writer';
@@ -0,0 +1,111 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { type Obj } from '@dxos/echo';
6
+ import { type SerializedSpace } from '@dxos/echo-db';
7
+ import { type DatabaseDirectory, type ObjectStructure } from '@dxos/echo-protocol';
8
+ import { assertArgument } from '@dxos/invariant';
9
+ import { type SpaceArchive } from '@dxos/protocols/proto/dxos/client/services';
10
+
11
+ const ATTR_TYPE = '@type';
12
+ const ATTR_META = '@meta';
13
+ const ATTR_DELETED = '@deleted';
14
+ const ATTR_PARENT = '@parent';
15
+ const ATTR_RELATION_SOURCE = '@relationSource';
16
+ const ATTR_RELATION_TARGET = '@relationTarget';
17
+
18
+ const INTERNAL_KEYS: ReadonlySet<string> = new Set([
19
+ 'id',
20
+ ATTR_TYPE,
21
+ ATTR_META,
22
+ ATTR_DELETED,
23
+ ATTR_PARENT,
24
+ ATTR_RELATION_SOURCE,
25
+ ATTR_RELATION_TARGET,
26
+ ]);
27
+
28
+ /**
29
+ * Parse a JSON space archive.
30
+ *
31
+ * The archive contents are expected to be the UTF-8 encoding of
32
+ * `JSON.stringify(serializedSpace)`.
33
+ */
34
+ export const readSerializedSpaceArchive = (archive: SpaceArchive): SerializedSpace => {
35
+ const text = new TextDecoder().decode(archive.contents);
36
+ const parsed = JSON.parse(text) as SerializedSpace;
37
+ assertArgument(typeof parsed === 'object' && parsed !== null, 'archive', 'Invalid JSON archive payload');
38
+ assertArgument(typeof parsed.version === 'number', 'archive', 'Missing SerializedSpace.version');
39
+ assertArgument(Array.isArray(parsed.objects), 'archive', 'Missing SerializedSpace.objects');
40
+ return parsed;
41
+ };
42
+
43
+ /**
44
+ * Convert an {@link Obj.JSON} back into an internal {@link ObjectStructure} suitable
45
+ * for embedding into a {@link DatabaseDirectory}.
46
+ */
47
+ export const objJsonToObjectStructure = (obj: Obj.JSON): ObjectStructure => {
48
+ const data: Record<string, unknown> = {};
49
+ for (const [key, value] of Object.entries(obj)) {
50
+ if (INTERNAL_KEYS.has(key)) {
51
+ continue;
52
+ }
53
+ data[key] = value;
54
+ }
55
+
56
+ const system: NonNullable<ObjectStructure['system']> = {};
57
+
58
+ const type = obj[ATTR_TYPE];
59
+ if (type) {
60
+ system.type = { '/': type as string };
61
+ }
62
+
63
+ const parent = (obj as any)[ATTR_PARENT];
64
+ if (typeof parent === 'string') {
65
+ system.parent = { '/': parent };
66
+ }
67
+
68
+ const relationSource = (obj as any)[ATTR_RELATION_SOURCE];
69
+ const relationTarget = (obj as any)[ATTR_RELATION_TARGET];
70
+ if (typeof relationSource === 'string' || typeof relationTarget === 'string') {
71
+ system.kind = 'relation';
72
+ if (typeof relationSource === 'string') {
73
+ system.source = { '/': relationSource };
74
+ }
75
+ if (typeof relationTarget === 'string') {
76
+ system.target = { '/': relationTarget };
77
+ }
78
+ } else {
79
+ system.kind = 'object';
80
+ }
81
+
82
+ if ((obj as any)[ATTR_DELETED]) {
83
+ system.deleted = true;
84
+ }
85
+
86
+ const meta = (obj as any)[ATTR_META];
87
+ return {
88
+ system,
89
+ meta: {
90
+ keys: meta?.keys ?? [],
91
+ ...(meta?.tags ? { tags: meta.tags } : {}),
92
+ },
93
+ data,
94
+ };
95
+ };
96
+
97
+ /**
98
+ * Build a new {@link DatabaseDirectory} containing every object from the archive,
99
+ * keyed by object id. The caller is responsible for stamping the `access.spaceKey`
100
+ * and version fields after the document is created.
101
+ */
102
+ export const buildDatabaseDirectoryFromObjects = (objects: readonly Obj.JSON[]): DatabaseDirectory => {
103
+ const map: Record<string, ObjectStructure> = {};
104
+ for (const obj of objects) {
105
+ map[obj.id] = objJsonToObjectStructure(obj);
106
+ }
107
+ return {
108
+ objects: map,
109
+ links: {},
110
+ };
111
+ };