@dxos/client-services 0.8.4-main.ae835ea → 0.8.4-main.bc674ce

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 (126) hide show
  1. package/dist/lib/browser/{chunk-KPYVJG6G.mjs → chunk-J33W6T4Q.mjs} +1025 -1331
  2. package/dist/lib/browser/chunk-J33W6T4Q.mjs.map +7 -0
  3. package/dist/lib/browser/chunk-NQSC7HOE.mjs +22 -0
  4. package/dist/lib/browser/chunk-NQSC7HOE.mjs.map +7 -0
  5. package/dist/lib/browser/chunk-QCWEHHJW.mjs +24 -0
  6. package/dist/lib/browser/chunk-QCWEHHJW.mjs.map +7 -0
  7. package/dist/lib/browser/index.mjs +432 -65
  8. package/dist/lib/browser/index.mjs.map +4 -4
  9. package/dist/lib/browser/meta.json +1 -1
  10. package/dist/lib/browser/packlets/diagnostics/browser-diagnostics-broadcast.mjs +93 -0
  11. package/dist/lib/browser/packlets/diagnostics/browser-diagnostics-broadcast.mjs.map +7 -0
  12. package/dist/lib/browser/packlets/diagnostics/diagnostics-broadcast.mjs +11 -0
  13. package/dist/lib/browser/packlets/diagnostics/diagnostics-broadcast.mjs.map +7 -0
  14. package/dist/lib/browser/packlets/locks/browser.mjs +126 -0
  15. package/dist/lib/browser/packlets/locks/browser.mjs.map +7 -0
  16. package/dist/lib/browser/packlets/locks/node.mjs +66 -0
  17. package/dist/lib/browser/packlets/locks/node.mjs.map +7 -0
  18. package/dist/lib/browser/testing/index.mjs +24 -12
  19. package/dist/lib/browser/testing/index.mjs.map +3 -3
  20. package/dist/lib/node-esm/chunk-2SZHAWBN.mjs +24 -0
  21. package/dist/lib/node-esm/chunk-2SZHAWBN.mjs.map +7 -0
  22. package/dist/lib/node-esm/{chunk-BBBSS6UL.mjs → chunk-34HKLADW.mjs} +517 -692
  23. package/dist/lib/node-esm/chunk-34HKLADW.mjs.map +7 -0
  24. package/dist/lib/node-esm/chunk-PKEGMOQ4.mjs +22 -0
  25. package/dist/lib/node-esm/chunk-PKEGMOQ4.mjs.map +7 -0
  26. package/dist/lib/node-esm/index.mjs +432 -65
  27. package/dist/lib/node-esm/index.mjs.map +4 -4
  28. package/dist/lib/node-esm/meta.json +1 -1
  29. package/dist/lib/node-esm/packlets/diagnostics/browser-diagnostics-broadcast.mjs +93 -0
  30. package/dist/lib/node-esm/packlets/diagnostics/browser-diagnostics-broadcast.mjs.map +7 -0
  31. package/dist/lib/node-esm/packlets/diagnostics/diagnostics-broadcast.mjs +11 -0
  32. package/dist/lib/node-esm/packlets/diagnostics/diagnostics-broadcast.mjs.map +7 -0
  33. package/dist/lib/node-esm/packlets/locks/browser.mjs +126 -0
  34. package/dist/lib/node-esm/packlets/locks/browser.mjs.map +7 -0
  35. package/dist/lib/node-esm/packlets/locks/node.mjs +66 -0
  36. package/dist/lib/node-esm/packlets/locks/node.mjs.map +7 -0
  37. package/dist/lib/node-esm/testing/index.mjs +24 -12
  38. package/dist/lib/node-esm/testing/index.mjs.map +3 -3
  39. package/dist/types/src/packlets/devtools/devtools.d.ts +2 -2
  40. package/dist/types/src/packlets/devtools/devtools.d.ts.map +1 -1
  41. package/dist/types/src/packlets/diagnostics/index.d.ts +1 -1
  42. package/dist/types/src/packlets/diagnostics/index.d.ts.map +1 -1
  43. package/dist/types/src/packlets/identity/authenticator.d.ts +2 -2
  44. package/dist/types/src/packlets/identity/authenticator.d.ts.map +1 -1
  45. package/dist/types/src/packlets/identity/default-space-state-machine.d.ts +2 -2
  46. package/dist/types/src/packlets/identity/default-space-state-machine.d.ts.map +1 -1
  47. package/dist/types/src/packlets/identity/identity-manager.d.ts +4 -4
  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.d.ts +2 -2
  52. package/dist/types/src/packlets/identity/identity.d.ts.map +1 -1
  53. package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts +4 -4
  54. package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts.map +1 -1
  55. package/dist/types/src/packlets/invitations/invitation-guest-extenstion.d.ts.map +1 -1
  56. package/dist/types/src/packlets/invitations/invitation-host-extension.d.ts.map +1 -1
  57. package/dist/types/src/packlets/invitations/invitation-protocol.d.ts +2 -3
  58. package/dist/types/src/packlets/invitations/invitation-protocol.d.ts.map +1 -1
  59. package/dist/types/src/packlets/invitations/invitations-handler.d.ts +4 -4
  60. package/dist/types/src/packlets/invitations/invitations-handler.d.ts.map +1 -1
  61. package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts +2 -2
  62. package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts.map +1 -1
  63. package/dist/types/src/packlets/locks/index.d.ts +1 -1
  64. package/dist/types/src/packlets/locks/index.d.ts.map +1 -1
  65. package/dist/types/src/packlets/services/client-rpc-server.d.ts +2 -2
  66. package/dist/types/src/packlets/services/client-rpc-server.d.ts.map +1 -1
  67. package/dist/types/src/packlets/services/service-context.d.ts +13 -7
  68. package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
  69. package/dist/types/src/packlets/services/service-host.d.ts +19 -5
  70. package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
  71. package/dist/types/src/packlets/space-export/space-archive-writer.d.ts.map +1 -1
  72. package/dist/types/src/packlets/spaces/data-space-manager.d.ts +10 -5
  73. package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
  74. package/dist/types/src/packlets/spaces/data-space.d.ts +2 -2
  75. package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
  76. package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts +2 -2
  77. package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts.map +1 -1
  78. package/dist/types/src/packlets/spaces/notarization-plugin.d.ts +6 -6
  79. package/dist/types/src/packlets/spaces/notarization-plugin.d.ts.map +1 -1
  80. package/dist/types/src/packlets/spaces/spaces-service.d.ts.map +1 -1
  81. package/dist/types/src/packlets/testing/invitation-utils.d.ts +6 -3
  82. package/dist/types/src/packlets/testing/invitation-utils.d.ts.map +1 -1
  83. package/dist/types/src/packlets/testing/test-builder.d.ts +6 -5
  84. package/dist/types/src/packlets/testing/test-builder.d.ts.map +1 -1
  85. package/dist/types/src/packlets/worker/worker-runtime.d.ts +23 -4
  86. package/dist/types/src/packlets/worker/worker-runtime.d.ts.map +1 -1
  87. package/dist/types/src/packlets/worker/worker-session.d.ts +2 -2
  88. package/dist/types/src/packlets/worker/worker-session.d.ts.map +1 -1
  89. package/dist/types/src/version.d.ts +1 -1
  90. package/dist/types/tsconfig.tsbuildinfo +1 -1
  91. package/package.json +70 -48
  92. package/src/packlets/devtools/devtools.ts +2 -2
  93. package/src/packlets/diagnostics/index.ts +1 -1
  94. package/src/packlets/identity/authenticator.ts +2 -2
  95. package/src/packlets/identity/default-space-state-machine.ts +2 -2
  96. package/src/packlets/identity/identity-manager.ts +6 -6
  97. package/src/packlets/identity/identity-recovery-manager.ts +2 -2
  98. package/src/packlets/identity/identity.ts +2 -2
  99. package/src/packlets/invitations/device-invitation-protocol.ts +5 -5
  100. package/src/packlets/invitations/invitation-guest-extenstion.ts +6 -4
  101. package/src/packlets/invitations/invitation-host-extension.ts +6 -4
  102. package/src/packlets/invitations/invitation-protocol.ts +2 -3
  103. package/src/packlets/invitations/invitations-handler.ts +7 -7
  104. package/src/packlets/invitations/space-invitation-protocol.ts +7 -13
  105. package/src/packlets/locks/index.ts +1 -1
  106. package/src/packlets/logging/logging-service.ts +1 -1
  107. package/src/packlets/services/client-rpc-server.ts +4 -4
  108. package/src/packlets/services/service-context.ts +30 -19
  109. package/src/packlets/services/service-host.ts +56 -16
  110. package/src/packlets/space-export/space-archive-reader.ts +1 -1
  111. package/src/packlets/space-export/space-archive-writer.ts +3 -1
  112. package/src/packlets/spaces/data-space-manager.ts +43 -20
  113. package/src/packlets/spaces/data-space.ts +7 -6
  114. package/src/packlets/spaces/edge-feed-replicator.ts +2 -2
  115. package/src/packlets/spaces/epoch-migrations.ts +2 -2
  116. package/src/packlets/spaces/notarization-plugin.test.ts +2 -2
  117. package/src/packlets/spaces/notarization-plugin.ts +8 -8
  118. package/src/packlets/spaces/spaces-service.ts +10 -7
  119. package/src/packlets/storage/storage.ts +4 -4
  120. package/src/packlets/testing/invitation-utils.ts +7 -4
  121. package/src/packlets/testing/test-builder.ts +36 -10
  122. package/src/packlets/worker/worker-runtime.ts +141 -11
  123. package/src/packlets/worker/worker-session.ts +4 -4
  124. package/src/version.ts +1 -1
  125. package/dist/lib/browser/chunk-KPYVJG6G.mjs.map +0 -7
  126. package/dist/lib/node-esm/chunk-BBBSS6UL.mjs.map +0 -7
@@ -2,6 +2,8 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
+ import type * as SqlClient from '@effect/sql/SqlClient';
6
+
5
7
  import { Mutex, Trigger } from '@dxos/async';
6
8
  import { Context, Resource } from '@dxos/context';
7
9
  import { type CredentialProcessor, getCredentialAssertion } from '@dxos/credentials';
@@ -16,6 +18,7 @@ import {
16
18
  } from '@dxos/echo-pipeline';
17
19
  import { createChainEdgeIdentity, createEphemeralEdgeIdentity } from '@dxos/edge-client';
18
20
  import type { EdgeConnection, EdgeHttpClient, EdgeIdentity } from '@dxos/edge-client';
21
+ import { type RuntimeProvider } from '@dxos/effect';
19
22
  import { FeedFactory, FeedStore } from '@dxos/feed-store';
20
23
  import { invariant } from '@dxos/invariant';
21
24
  import { Keyring } from '@dxos/keyring';
@@ -30,6 +33,7 @@ import { type Runtime } from '@dxos/protocols/proto/dxos/config';
30
33
  import type { FeedMessage } from '@dxos/protocols/proto/dxos/echo/feed';
31
34
  import { type Credential, type ProfileDocument } from '@dxos/protocols/proto/dxos/halo/credentials';
32
35
  import { type Storage } from '@dxos/random-access-storage';
36
+ import type * as SqlTransaction from '@dxos/sql-sqlite/SqlTransaction';
33
37
  import { BlobStore } from '@dxos/teleport-extension-object-sync';
34
38
  import { trace as Trace } from '@dxos/tracing';
35
39
  import { safeInstanceof } from '@dxos/util';
@@ -38,28 +42,30 @@ import { EdgeAgentManager } from '../agents';
38
42
  import {
39
43
  type CreateIdentityOptions,
40
44
  IdentityManager,
41
- type IdentityManagerParams,
42
- type JoinIdentityParams,
45
+ type IdentityManagerProps,
46
+ type JoinIdentityProps,
43
47
  } from '../identity';
44
48
  import { EdgeIdentityRecoveryManager } from '../identity/identity-recovery-manager';
45
49
  import {
46
50
  DeviceInvitationProtocol,
47
- type InvitationConnectionParams,
51
+ type InvitationConnectionProps,
48
52
  type InvitationProtocol,
49
53
  InvitationsHandler,
50
54
  InvitationsManager,
51
55
  SpaceInvitationProtocol,
52
56
  } from '../invitations';
53
- import { DataSpaceManager, type DataSpaceManagerRuntimeParams, type SigningContext } from '../spaces';
57
+ import { DataSpaceManager, type DataSpaceManagerRuntimeProps, type SigningContext } from '../spaces';
54
58
 
55
- export type ServiceContextRuntimeParams = Pick<
56
- IdentityManagerParams,
59
+ export type ServiceContextRuntimeProps = Pick<
60
+ IdentityManagerProps,
57
61
  'devicePresenceOfflineTimeout' | 'devicePresenceAnnounceInterval'
58
62
  > &
59
- DataSpaceManagerRuntimeParams & {
60
- invitationConnectionDefaultParams?: InvitationConnectionParams;
63
+ DataSpaceManagerRuntimeProps & {
64
+ invitationConnectionDefaultProps?: InvitationConnectionProps;
61
65
  disableP2pReplication?: boolean;
62
66
  enableVectorIndexing?: boolean;
67
+ enableSqlite?: boolean;
68
+ enableLocalQueues?: boolean;
63
69
  };
64
70
  /**
65
71
  * Shared backend for all client services.
@@ -105,11 +111,15 @@ export class ServiceContext extends Resource {
105
111
  public readonly signalManager: SignalManager,
106
112
  private readonly _edgeConnection: EdgeConnection | undefined,
107
113
  private readonly _edgeHttpClient: EdgeHttpClient | undefined,
108
- public readonly _runtimeParams?: ServiceContextRuntimeParams,
114
+ private readonly _runtime: RuntimeProvider.RuntimeProvider<SqlClient.SqlClient | SqlTransaction.SqlTransaction>,
115
+ public readonly _runtimeProps?: ServiceContextRuntimeProps,
109
116
  private readonly _edgeFeatures?: Runtime.Client.EdgeFeatures,
110
117
  ) {
111
118
  super();
112
119
 
120
+ log('runtimeProps', this._runtimeProps);
121
+ log('edgeFeatures', this._edgeFeatures);
122
+
113
123
  // TODO(burdon): Move strings to constants.
114
124
  this.metadataStore = new MetadataStore(storage.createDirectory('metadata'));
115
125
  this.blobStore = new BlobStore(storage.createDirectory('blobs'));
@@ -131,7 +141,7 @@ export class ServiceContext extends Resource {
131
141
  networkManager: this.networkManager,
132
142
  blobStore: this.blobStore,
133
143
  metadataStore: this.metadataStore,
134
- disableP2pReplication: this._runtimeParams?.disableP2pReplication,
144
+ disableP2pReplication: this._runtimeProps?.disableP2pReplication,
135
145
  });
136
146
 
137
147
  this.identityManager = new IdentityManager({
@@ -139,8 +149,8 @@ export class ServiceContext extends Resource {
139
149
  keyring: this.keyring,
140
150
  feedStore: this.feedStore,
141
151
  spaceManager: this.spaceManager,
142
- devicePresenceOfflineTimeout: this._runtimeParams?.devicePresenceOfflineTimeout,
143
- devicePresenceAnnounceInterval: this._runtimeParams?.devicePresenceAnnounceInterval,
152
+ devicePresenceOfflineTimeout: this._runtimeProps?.devicePresenceOfflineTimeout,
153
+ devicePresenceAnnounceInterval: this._runtimeProps?.devicePresenceAnnounceInterval,
144
154
  edgeConnection: this._edgeConnection,
145
155
  edgeFeatures: this._edgeFeatures,
146
156
  });
@@ -157,16 +167,17 @@ export class ServiceContext extends Resource {
157
167
  peerIdProvider: () => this.identityManager.identity?.deviceKey?.toHex(),
158
168
  getSpaceKeyByRootDocumentId: (documentId) => this.spaceManager.findSpaceByRootDocumentId(documentId)?.key,
159
169
  indexing: {
160
- vector: this._runtimeParams?.enableVectorIndexing,
170
+ vector: this._runtimeProps?.enableVectorIndexing,
171
+ sqlIndex: this._runtimeProps?.enableSqlite,
161
172
  },
173
+ runtime: this._runtime,
174
+ localQueues: this._runtimeProps?.enableLocalQueues,
162
175
  });
163
176
 
164
- this._meshReplicator = new MeshEchoReplicator();
165
-
166
177
  this.invitations = new InvitationsHandler(
167
178
  this.networkManager, //
168
179
  this._edgeHttpClient,
169
- _runtimeParams?.invitationConnectionDefaultParams,
180
+ _runtimeProps?.invitationConnectionDefaultProps,
170
181
  );
171
182
  this.invitationsManager = new InvitationsManager(
172
183
  this.invitations,
@@ -186,7 +197,7 @@ export class ServiceContext extends Resource {
186
197
  ),
187
198
  );
188
199
 
189
- if (!this._runtimeParams?.disableP2pReplication) {
200
+ if (!this._runtimeProps?.disableP2pReplication) {
190
201
  this._meshReplicator = new MeshEchoReplicator();
191
202
  }
192
203
  if (this._edgeConnection && this._edgeFeatures?.echoReplicator && this._edgeHttpClient) {
@@ -283,7 +294,7 @@ export class ServiceContext extends Resource {
283
294
  }
284
295
  }
285
296
 
286
- private async _acceptIdentity(params: JoinIdentityParams) {
297
+ private async _acceptIdentity(params: JoinIdentityProps) {
287
298
  const { identity, identityRecord } = await this.identityManager.prepareIdentity(params);
288
299
  await this._setNetworkIdentity({ deviceCredential: params.authorizedDeviceCredential! });
289
300
  await identity.joinNetwork();
@@ -327,7 +338,7 @@ export class ServiceContext extends Resource {
327
338
  edgeHttpClient: this._edgeHttpClient,
328
339
  echoEdgeReplicator: this._echoEdgeReplicator,
329
340
  meshReplicator: this._meshReplicator,
330
- runtimeParams: this._runtimeParams as DataSpaceManagerRuntimeParams,
341
+ runtimeProps: this._runtimeProps as DataSpaceManagerRuntimeProps,
331
342
  edgeFeatures: this._edgeFeatures,
332
343
  });
333
344
  await this.dataSpaceManager.open();
@@ -2,11 +2,15 @@
2
2
  // Copyright 2021 DXOS.org
3
3
  //
4
4
 
5
+ import * as SqlClient from '@effect/sql/SqlClient';
6
+ import * as Effect from 'effect/Effect';
7
+
5
8
  import { Event, synchronized } from '@dxos/async';
6
9
  import { type ClientServices, clientServiceBundle } from '@dxos/client-protocol';
7
10
  import { type Config } from '@dxos/config';
8
11
  import { Context } from '@dxos/context';
9
12
  import { EdgeClient, type EdgeConnection, EdgeHttpClient, createStubEdgeIdentity } from '@dxos/edge-client';
13
+ import { RuntimeProvider } from '@dxos/effect';
10
14
  import { invariant } from '@dxos/invariant';
11
15
  import { PublicKey } from '@dxos/keys';
12
16
  import { type LevelDB } from '@dxos/kv-store';
@@ -21,6 +25,8 @@ import {
21
25
  import { trace } from '@dxos/protocols';
22
26
  import { SystemStatus } from '@dxos/protocols/proto/dxos/client/services';
23
27
  import { type Storage } from '@dxos/random-access-storage';
28
+ import * as SqlExport from '@dxos/sql-sqlite/SqlExport';
29
+ import type * as SqlTransaction from '@dxos/sql-sqlite/SqlTransaction';
24
30
  import { TRACE_PROCESSOR, trace as Trace } from '@dxos/tracing';
25
31
  import { WebsocketRpcClient } from '@dxos/websocket-rpc';
26
32
 
@@ -42,10 +48,10 @@ import { SpacesServiceImpl } from '../spaces';
42
48
  import { createLevel, createStorageObjects } from '../storage';
43
49
  import { SystemServiceImpl } from '../system';
44
50
 
45
- import { ServiceContext, type ServiceContextRuntimeParams } from './service-context';
51
+ import { ServiceContext, type ServiceContextRuntimeProps } from './service-context';
46
52
  import { ServiceRegistry } from './service-registry';
47
53
 
48
- export type ClientServicesHostParams = {
54
+ export type ClientServicesHostProps = {
49
55
  /**
50
56
  * Can be omitted if `initialize` is later called.
51
57
  */
@@ -57,7 +63,8 @@ export type ClientServicesHostParams = {
57
63
  level?: LevelDB;
58
64
  lockKey?: string;
59
65
  callbacks?: ClientServicesHostCallbacks;
60
- runtimeParams?: ServiceContextRuntimeParams;
66
+ runtime: RuntimeProvider.RuntimeProvider<SqlClient.SqlClient | SqlExport.SqlExport | SqlTransaction.SqlTransaction>;
67
+ runtimeProps?: ServiceContextRuntimeProps;
61
68
  };
62
69
 
63
70
  export type ClientServicesHostCallbacks = {
@@ -95,7 +102,10 @@ export class ClientServicesHost {
95
102
  private _edgeHttpClient?: EdgeHttpClient = undefined;
96
103
 
97
104
  private _serviceContext!: ServiceContext;
98
- private readonly _runtimeParams: ServiceContextRuntimeParams;
105
+ private readonly _runtime: RuntimeProvider.RuntimeProvider<
106
+ SqlClient.SqlClient | SqlExport.SqlExport | SqlTransaction.SqlTransaction
107
+ >;
108
+ private readonly _runtimeProps: ServiceContextRuntimeProps;
99
109
  private diagnosticsBroadcastHandler: CollectDiagnosticsBroadcastHandler;
100
110
 
101
111
  @Trace.info()
@@ -116,20 +126,14 @@ export class ClientServicesHost {
116
126
  // TODO(wittjosiah): Turn this on by default.
117
127
  lockKey,
118
128
  callbacks,
119
- runtimeParams,
120
- }: ClientServicesHostParams = {}) {
129
+ runtime,
130
+ runtimeProps,
131
+ }: ClientServicesHostProps) {
121
132
  this._storage = storage;
122
133
  this._level = level;
123
134
  this._callbacks = callbacks;
124
- this._runtimeParams = runtimeParams ?? {};
125
-
126
- if (this._runtimeParams.disableP2pReplication === undefined) {
127
- this._runtimeParams.disableP2pReplication = config?.get('runtime.client.disableP2pReplication', false);
128
- }
129
-
130
- if (this._runtimeParams.enableVectorIndexing === undefined) {
131
- this._runtimeParams.enableVectorIndexing = config?.get('runtime.client.enableVectorIndexing', false);
132
- }
135
+ this._runtime = runtime;
136
+ this._runtimeProps = runtimeProps ?? {};
133
137
 
134
138
  if (config) {
135
139
  this.initialize({ config, transportFactory, signalManager });
@@ -200,6 +204,30 @@ export class ClientServicesHost {
200
204
  return this._serviceRegistry.services;
201
205
  }
202
206
 
207
+ /**
208
+ * Debugging util.
209
+ */
210
+ async exportSqliteDatabase(): Promise<Uint8Array> {
211
+ return await RuntimeProvider.runPromise(this._runtime)(
212
+ Effect.gen(function* () {
213
+ const sql = yield* SqlExport.SqlExport;
214
+ return yield* sql.export;
215
+ }),
216
+ );
217
+ }
218
+
219
+ /**
220
+ * Debugging util.
221
+ */
222
+ async runSqliteQuery(query: string, params?: any[]): Promise<readonly Record<string, unknown>[]> {
223
+ return await RuntimeProvider.runPromise(this._runtime)(
224
+ Effect.gen(function* () {
225
+ const sql = yield* SqlClient.SqlClient;
226
+ return yield* sql`${sql.unsafe(query, params)}`;
227
+ }),
228
+ );
229
+ }
230
+
203
231
  /**
204
232
  * Initialize the service host with the config.
205
233
  * Config can also be provided in the constructor.
@@ -210,6 +238,16 @@ export class ClientServicesHost {
210
238
  log('initializing...');
211
239
 
212
240
  if (config) {
241
+ if (this._runtimeProps.disableP2pReplication === undefined) {
242
+ this._runtimeProps.disableP2pReplication = config?.get('runtime.client.disableP2pReplication', false);
243
+ }
244
+ if (this._runtimeProps.enableVectorIndexing === undefined) {
245
+ this._runtimeProps.enableVectorIndexing = config?.get('runtime.client.enableVectorIndexing', false);
246
+ }
247
+ if (this._runtimeProps.enableLocalQueues === undefined) {
248
+ this._runtimeProps.enableLocalQueues = config?.get('runtime.client.enableLocalQueues', false);
249
+ }
250
+
213
251
  invariant(!this._config, 'config already set');
214
252
  this._config = config;
215
253
  if (!this._storage) {
@@ -291,7 +329,8 @@ export class ClientServicesHost {
291
329
  this._signalManager,
292
330
  this._edgeConnection,
293
331
  this._edgeHttpClient,
294
- this._runtimeParams,
332
+ this._runtime,
333
+ this._runtimeProps,
295
334
  this._config.get('runtime.client.edgeFeatures'),
296
335
  );
297
336
 
@@ -335,6 +374,7 @@ export class ClientServicesHost {
335
374
 
336
375
  DataService: this._serviceContext.echoHost.dataService,
337
376
  QueryService: this._serviceContext.echoHost.queryService,
377
+ QueueService: this._serviceContext.echoHost.queuesService,
338
378
 
339
379
  NetworkService: new NetworkServiceImpl(
340
380
  this._serviceContext.networkManager,
@@ -29,6 +29,6 @@ export const extractSpaceArchive = async (archive: SpaceArchive): Promise<Extrac
29
29
  documents[documentId] = entry.content ?? failedInvariant();
30
30
  }
31
31
 
32
- log.info('extracted space archive', { metadata, documents });
32
+ log('extracted space archive', { metadata, documents });
33
33
  return { metadata, documents };
34
34
  };
@@ -9,6 +9,7 @@ import { assertArgument, assertState } from '@dxos/invariant';
9
9
  import type { IdentityDid, SpaceId } from '@dxos/keys';
10
10
  import { SpaceArchiveFileStructure, type SpaceArchiveMetadata, SpaceArchiveVersion } from '@dxos/protocols';
11
11
  import type { SpaceArchive } from '@dxos/protocols/proto/dxos/client/services';
12
+ import { createFilename } from '@dxos/util';
12
13
 
13
14
  export type SpaceArchiveBeginProps = {
14
15
  spaceId?: SpaceId;
@@ -59,6 +60,7 @@ export class SpaceArchiveWriter extends Resource {
59
60
  async finish(): Promise<SpaceArchive> {
60
61
  assertState(this._archive, 'Not open');
61
62
  assertState(this._meta, 'Not started');
63
+ assertState(this._meta.spaceId, 'No space ID set');
62
64
  assertState(this._currentRootUrl, 'No root URL set');
63
65
 
64
66
  const metadata: SpaceArchiveMetadata = {
@@ -76,7 +78,7 @@ export class SpaceArchiveWriter extends Resource {
76
78
  const binary = this._archive.toUint8Array();
77
79
 
78
80
  return {
79
- filename: `${this._meta.spaceId}.tar`,
81
+ filename: createFilename({ parts: [this._meta.spaceId], ext: 'tar' }),
80
82
  contents: binary,
81
83
  };
82
84
  }
@@ -6,7 +6,7 @@ import { type Doc } from '@automerge/automerge';
6
6
  import { type AutomergeUrl, type DocHandle, type DocumentId, interpretAsDocumentId } from '@automerge/automerge-repo';
7
7
 
8
8
  import { Event, synchronized, trackLeaks } from '@dxos/async';
9
- import { PropertiesType, TYPE_PROPERTIES } from '@dxos/client-protocol';
9
+ import { SpaceProperties } from '@dxos/client-protocol';
10
10
  import { Context, LifecycleState, Resource, cancelWithContext } from '@dxos/context';
11
11
  import {
12
12
  type CredentialSigner,
@@ -15,14 +15,14 @@ import {
15
15
  createAdmissionCredentials,
16
16
  getCredentialAssertion,
17
17
  } from '@dxos/credentials';
18
- import { ObjectId, getTypeReference } from '@dxos/echo/internal';
18
+ import { Type } from '@dxos/echo';
19
+ import { getSchemaDXN } from '@dxos/echo/internal';
19
20
  import {
20
21
  AuthStatus,
21
22
  CredentialServerExtension,
22
23
  DatabaseRoot,
23
24
  type EchoEdgeReplicator,
24
25
  type EchoHost,
25
- FIND_PARAMS,
26
26
  type MeshEchoReplicator,
27
27
  type MetadataStore,
28
28
  type Space,
@@ -33,16 +33,16 @@ import {
33
33
  } from '@dxos/echo-pipeline';
34
34
  import {
35
35
  type DatabaseDirectory,
36
+ EncodedReference,
36
37
  type ObjectStructure,
37
38
  SpaceDocVersion,
38
39
  createIdFromSpaceKey,
39
- encodeReference,
40
40
  } from '@dxos/echo-protocol';
41
41
  import type { EdgeConnection, EdgeHttpClient } from '@dxos/edge-client';
42
42
  import { type FeedStore, writeMessages } from '@dxos/feed-store';
43
43
  import { assertArgument, assertState, failedInvariant, invariant } from '@dxos/invariant';
44
44
  import { type Keyring } from '@dxos/keyring';
45
- import { PublicKey, type SpaceId } from '@dxos/keys';
45
+ import { ObjectId, PublicKey, type SpaceId } from '@dxos/keys';
46
46
  import { log } from '@dxos/log';
47
47
  import { AlreadyJoinedError, trace as Trace } from '@dxos/protocols';
48
48
  import { Invitation, SpaceState } from '@dxos/protocols/proto/dxos/client/services';
@@ -104,7 +104,7 @@ export type AdmitMemberOptions = {
104
104
  delegationCredentialId?: PublicKey;
105
105
  };
106
106
 
107
- export type DataSpaceManagerParams = {
107
+ export type DataSpaceManagerProps = {
108
108
  spaceManager: SpaceManager;
109
109
  metadataStore: MetadataStore;
110
110
  keyring: Keyring;
@@ -116,15 +116,20 @@ export type DataSpaceManagerParams = {
116
116
  edgeHttpClient?: EdgeHttpClient;
117
117
  meshReplicator?: MeshEchoReplicator;
118
118
  echoEdgeReplicator?: EchoEdgeReplicator;
119
- runtimeParams?: DataSpaceManagerRuntimeParams;
119
+ runtimeProps?: DataSpaceManagerRuntimeProps;
120
120
  edgeFeatures?: Runtime.Client.EdgeFeatures;
121
121
  };
122
122
 
123
- export type DataSpaceManagerRuntimeParams = {
123
+ export type DataSpaceManagerRuntimeProps = {
124
124
  spaceMemberPresenceAnnounceInterval?: number;
125
125
  spaceMemberPresenceOfflineTimeout?: number;
126
126
  activeEdgeNotarizationPollingInterval?: number;
127
127
  disableP2pReplication?: boolean;
128
+ /**
129
+ * If true, spaces that were previously SPACE_ACTIVE will be automatically activated on startup.
130
+ * This is used in dedicated worker mode to restore space state after leader changeover.
131
+ */
132
+ autoActivateSpaces?: boolean;
128
133
  };
129
134
 
130
135
  export type CreateSpaceOptions = {
@@ -152,9 +157,9 @@ export class DataSpaceManager extends Resource {
152
157
  private readonly _edgeFeatures?: Runtime.Client.EdgeFeatures = undefined;
153
158
  private readonly _meshReplicator?: MeshEchoReplicator = undefined;
154
159
  private readonly _echoEdgeReplicator?: EchoEdgeReplicator = undefined;
155
- private readonly _runtimeParams?: DataSpaceManagerRuntimeParams = undefined;
160
+ private readonly _runtimeProps?: DataSpaceManagerRuntimeProps = undefined;
156
161
 
157
- constructor(params: DataSpaceManagerParams) {
162
+ constructor(params: DataSpaceManagerProps) {
158
163
  super();
159
164
 
160
165
  this._spaceManager = params.spaceManager;
@@ -169,7 +174,7 @@ export class DataSpaceManager extends Resource {
169
174
  this._edgeFeatures = params.edgeFeatures;
170
175
  this._echoEdgeReplicator = params.echoEdgeReplicator;
171
176
  this._edgeHttpClient = params.edgeHttpClient;
172
- this._runtimeParams = params.runtimeParams;
177
+ this._runtimeProps = params.runtimeProps;
173
178
 
174
179
  trace.diagnostic({
175
180
  id: 'spaces',
@@ -179,12 +184,12 @@ export class DataSpaceManager extends Resource {
179
184
  Array.from(this._spaces.values()).map(async (space) => {
180
185
  const rootUrl = space.automergeSpaceState.rootUrl;
181
186
  const rootHandle = rootUrl
182
- ? await this._echoHost.automergeRepo.find<Doc<DatabaseDirectory>>(rootUrl as AutomergeUrl, FIND_PARAMS)
187
+ ? await this._echoHost.loadDoc<Doc<DatabaseDirectory>>(Context.default(), rootUrl as AutomergeUrl)
183
188
  : undefined;
184
189
  await rootHandle?.whenReady();
185
190
  const rootDoc = rootHandle?.doc();
186
191
 
187
- const properties = rootDoc && findInlineObjectOfType(rootDoc, TYPE_PROPERTIES);
192
+ const properties = rootDoc && findInlineObjectOfType(rootDoc, Type.getTypename(SpaceProperties));
188
193
 
189
194
  return {
190
195
  key: space.key.toHex(),
@@ -217,15 +222,28 @@ export class DataSpaceManager extends Resource {
217
222
  log.trace('dxos.echo.data-space-manager.open', Trace.begin({ id: this._instanceId }));
218
223
  log('metadata loaded', { spaces: this._metadataStore.spaces.length });
219
224
 
225
+ const spacesToActivate: DataSpace[] = [];
220
226
  await forEachAsync(this._metadataStore.spaces, async (spaceMetadata) => {
221
227
  try {
222
228
  log('load space', { spaceMetadata });
223
- await this._constructSpace(spaceMetadata);
229
+ const space = await this._constructSpace(spaceMetadata);
230
+ // Track spaces that were previously active for auto-activation (used in dedicated worker mode).
231
+ if (this._runtimeProps?.autoActivateSpaces && spaceMetadata.state === SpaceState.SPACE_ACTIVE) {
232
+ spacesToActivate.push(space);
233
+ }
224
234
  } catch (err) {
225
235
  log.error('Error loading space', { spaceMetadata, err });
226
236
  }
227
237
  });
228
238
 
239
+ // Auto-activate spaces that were previously active (used in dedicated worker mode after leader changeover).
240
+ for (const space of spacesToActivate) {
241
+ log('auto-activating space', { spaceKey: space.key });
242
+ space.activate().catch((err) => {
243
+ log.error('Error auto-activating space', { spaceKey: space.key, err });
244
+ });
245
+ }
246
+
229
247
  this.updated.emit();
230
248
 
231
249
  log.trace('dxos.echo.data-space-manager.open', Trace.end({ id: this._instanceId }));
@@ -342,9 +360,12 @@ export class DataSpaceManager extends Resource {
342
360
  log.warn('waiting for space root to be ready', { spaceId: space.id });
343
361
  await space.databaseRoot.handle.whenReady();
344
362
  }
345
- const [_, properties] = findInlineObjectOfType(space.databaseRoot.doc()!, TYPE_PROPERTIES) ?? [];
363
+
364
+ const [_, properties] =
365
+ findInlineObjectOfType(space.databaseRoot.doc()!, Type.getTypename(SpaceProperties)) ?? [];
346
366
  return properties?.data?.[DEFAULT_SPACE_KEY] === this._signingContext.identityKey.toHex();
347
367
  }
368
+
348
369
  case SpaceDocVersion.LEGACY: {
349
370
  throw new Error('Legacy space version is not supported');
350
371
  }
@@ -362,7 +383,7 @@ export class DataSpaceManager extends Resource {
362
383
  // TODO(dmaretskyi): Better API for low-level data access.
363
384
  const properties: ObjectStructure = {
364
385
  system: {
365
- type: encodeReference(getTypeReference(PropertiesType)!),
386
+ type: EncodedReference.fromDXN(getSchemaDXN(SpaceProperties)!),
366
387
  },
367
388
  data: {
368
389
  [DEFAULT_SPACE_KEY]: this._signingContext.identityKey.toHex(),
@@ -384,7 +405,9 @@ export class DataSpaceManager extends Resource {
384
405
  private async _getSpaceRootDocument(space: DataSpace): Promise<DocHandle<DatabaseDirectory>> {
385
406
  const automergeIndex = space.automergeSpaceState.rootUrl;
386
407
  invariant(automergeIndex);
387
- const document = await this._echoHost.automergeRepo.find<DatabaseDirectory>(automergeIndex as any, FIND_PARAMS);
408
+ const document = await this._echoHost.loadDoc<DatabaseDirectory>(Context.default(), automergeIndex as any, {
409
+ fetchFromNetwork: true,
410
+ });
388
411
  await document.whenReady();
389
412
  return document;
390
413
  }
@@ -496,8 +519,8 @@ export class DataSpaceManager extends Resource {
496
519
  localPeerId: this._signingContext.deviceKey,
497
520
  });
498
521
  const presence = new Presence({
499
- announceInterval: this._runtimeParams?.spaceMemberPresenceAnnounceInterval ?? PRESENCE_ANNOUNCE_INTERVAL,
500
- offlineTimeout: this._runtimeParams?.spaceMemberPresenceOfflineTimeout ?? PRESENCE_OFFLINE_TIMEOUT,
522
+ announceInterval: this._runtimeProps?.spaceMemberPresenceAnnounceInterval ?? PRESENCE_ANNOUNCE_INTERVAL,
523
+ offlineTimeout: this._runtimeProps?.spaceMemberPresenceOfflineTimeout ?? PRESENCE_OFFLINE_TIMEOUT,
501
524
  identityKey: this._signingContext.identityKey,
502
525
  gossip,
503
526
  });
@@ -583,7 +606,7 @@ export class DataSpaceManager extends Resource {
583
606
  edgeConnection: this._edgeConnection,
584
607
  edgeHttpClient: this._edgeHttpClient,
585
608
  edgeFeatures: this._edgeFeatures,
586
- activeEdgeNotarizationPollingInterval: this._runtimeParams?.activeEdgeNotarizationPollingInterval,
609
+ activeEdgeNotarizationPollingInterval: this._runtimeProps?.activeEdgeNotarizationPollingInterval,
587
610
  });
588
611
  dataSpace.postOpen.append(async () => {
589
612
  const setting = dataSpace.getEdgeReplicationSetting();
@@ -3,7 +3,7 @@
3
3
  //
4
4
 
5
5
  import { save } from '@automerge/automerge';
6
- import { type DocHandle } from '@automerge/automerge-repo';
6
+ import { type AutomergeUrl, type DocHandle } from '@automerge/automerge-repo';
7
7
 
8
8
  import { Event, Mutex, scheduleTask, sleep, synchronized, trackLeaks } from '@dxos/async';
9
9
  import { AUTH_TIMEOUT } from '@dxos/client-protocol';
@@ -13,7 +13,6 @@ import { timed, warnAfterTimeout } from '@dxos/debug';
13
13
  import {
14
14
  type DatabaseRoot,
15
15
  type EchoHost,
16
- FIND_PARAMS,
17
16
  type MetadataStore,
18
17
  type Space,
19
18
  createMappedFeedWriter,
@@ -72,7 +71,7 @@ export type DataSpaceCallbacks = {
72
71
  beforeClose?: () => Promise<void>;
73
72
  };
74
73
 
75
- export type DataSpaceParams = {
74
+ export type DataSpaceProps = {
76
75
  initialState: SpaceState;
77
76
  inner: Space;
78
77
  metadataStore: MetadataStore;
@@ -136,7 +135,7 @@ export class DataSpace {
136
135
 
137
136
  public metrics: SpaceProto.Metrics = {};
138
137
 
139
- constructor(params: DataSpaceParams) {
138
+ constructor(params: DataSpaceProps) {
140
139
  this._inner = params.inner;
141
140
  this._inner.stateUpdate.on(this._ctx, () => this.stateUpdate.emit());
142
141
 
@@ -331,7 +330,7 @@ export class DataSpace {
331
330
  @trace.span({ showInBrowserTimeline: true })
332
331
  async initializeDataPipeline(): Promise<void> {
333
332
  if (this._state !== SpaceState.SPACE_CONTROL_ONLY) {
334
- throw new SystemError('Invalid operation');
333
+ throw new SystemError({ message: 'Invalid operation' });
335
334
  }
336
335
 
337
336
  this._state = SpaceState.SPACE_INITIALIZING;
@@ -471,7 +470,9 @@ export class DataSpace {
471
470
  await warnAfterTimeout(5_000, 'Automerge root doc load timeout (DataSpace)', async () => {
472
471
  handle = await cancelWithContext(
473
472
  this._ctx,
474
- this._echoHost.automergeRepo.find<DatabaseDirectory>(rootUrl as any, FIND_PARAMS),
473
+ this._echoHost.loadDoc<DatabaseDirectory>(Context.default(), rootUrl as AutomergeUrl, {
474
+ fetchFromNetwork: true,
475
+ }),
475
476
  );
476
477
  await cancelWithContext(this._ctx, handle.whenReady());
477
478
  });
@@ -22,7 +22,7 @@ import type { FeedBlock, ProtocolMessage } from '@dxos/protocols/feed-replicatio
22
22
  import { EdgeStatus } from '@dxos/protocols/proto/dxos/client/services';
23
23
  import { ComplexMap, arrayToBuffer, bufferToArray, defaultMap, rangeFromTo } from '@dxos/util';
24
24
 
25
- export type EdgeFeedReplicatorParams = {
25
+ export type EdgeFeedReplicatorProps = {
26
26
  messenger: EdgeConnection;
27
27
  spaceId: SpaceId;
28
28
  };
@@ -47,7 +47,7 @@ export class EdgeFeedReplicator extends Resource {
47
47
  */
48
48
  private _pushMutex = new ComplexMap<PublicKey, Mutex>(PublicKey.hash);
49
49
 
50
- constructor({ messenger, spaceId }: EdgeFeedReplicatorParams) {
50
+ constructor({ messenger, spaceId }: EdgeFeedReplicatorProps) {
51
51
  super();
52
52
  this._messenger = messenger;
53
53
  this._spaceId = spaceId;
@@ -36,7 +36,7 @@ const LOAD_DOC_TIMEOUT = 10_000;
36
36
  export const runEpochMigration = async (ctx: Context, context: MigrationContext): Promise<MigrationResult> => {
37
37
  switch (context.migration) {
38
38
  case CreateEpochRequest.Migration.INIT_AUTOMERGE: {
39
- const document = context.echoHost.createDoc();
39
+ const document = await context.echoHost.createDoc();
40
40
  await context.echoHost.flush();
41
41
  return { newRoot: document.url };
42
42
  }
@@ -48,7 +48,7 @@ export const runEpochMigration = async (ctx: Context, context: MigrationContext)
48
48
  timeout: LOAD_DOC_TIMEOUT,
49
49
  });
50
50
 
51
- const newRoot = context.echoHost.createDoc(rootHandle.doc());
51
+ const newRoot = await context.echoHost.createDoc(rootHandle.doc());
52
52
  await context.echoHost.flush();
53
53
  return { newRoot: newRoot.url };
54
54
  }
@@ -13,7 +13,7 @@ import { log } from '@dxos/log';
13
13
  import { AdmittedFeed, type Credential } from '@dxos/protocols/proto/dxos/halo/credentials';
14
14
  import { TestBuilder, type TestConnection, TestPeer } from '@dxos/teleport/testing';
15
15
 
16
- import { NotarizationPlugin, type NotarizationPluginParams } from './notarization-plugin';
16
+ import { NotarizationPlugin, type NotarizationPluginProps } from './notarization-plugin';
17
17
 
18
18
  class TestAgent extends TestPeer {
19
19
  private readonly _ctx = new Context();
@@ -21,7 +21,7 @@ class TestAgent extends TestPeer {
21
21
  feed = new MockFeedWriter<Credential>();
22
22
  notarizationPlugin: NotarizationPlugin;
23
23
 
24
- constructor(params: NotarizationPluginParams) {
24
+ constructor(params: NotarizationPluginProps) {
25
25
  super();
26
26
  this.notarizationPlugin = new NotarizationPlugin(params);
27
27
  this.feed.written.on(this._ctx, async ([credential]) => {