@dxos/client-services 0.8.4-main.7ace549 → 0.8.4-main.937b3ca

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 (111) hide show
  1. package/dist/lib/browser/chunk-NQSC7HOE.mjs +22 -0
  2. package/dist/lib/browser/chunk-NQSC7HOE.mjs.map +7 -0
  3. package/dist/lib/browser/chunk-QCWEHHJW.mjs +24 -0
  4. package/dist/lib/browser/chunk-QCWEHHJW.mjs.map +7 -0
  5. package/dist/lib/browser/{chunk-NXGWBEOK.mjs → chunk-UDCUM4WV.mjs} +922 -1265
  6. package/dist/lib/browser/chunk-UDCUM4WV.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-PKEGMOQ4.mjs +22 -0
  23. package/dist/lib/node-esm/chunk-PKEGMOQ4.mjs.map +7 -0
  24. package/dist/lib/node-esm/{chunk-AO4R6IID.mjs → chunk-Q56HAUWS.mjs} +421 -633
  25. package/dist/lib/node-esm/chunk-Q56HAUWS.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 +2 -2
  54. package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts.map +1 -1
  55. package/dist/types/src/packlets/invitations/invitations-handler.d.ts +4 -4
  56. package/dist/types/src/packlets/invitations/invitations-handler.d.ts.map +1 -1
  57. package/dist/types/src/packlets/locks/index.d.ts +1 -1
  58. package/dist/types/src/packlets/locks/index.d.ts.map +1 -1
  59. package/dist/types/src/packlets/services/client-rpc-server.d.ts +2 -2
  60. package/dist/types/src/packlets/services/client-rpc-server.d.ts.map +1 -1
  61. package/dist/types/src/packlets/services/service-context.d.ts +13 -7
  62. package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
  63. package/dist/types/src/packlets/services/service-host.d.ts +19 -5
  64. package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
  65. package/dist/types/src/packlets/space-export/space-archive-writer.d.ts.map +1 -1
  66. package/dist/types/src/packlets/spaces/data-space-manager.d.ts +10 -5
  67. package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
  68. package/dist/types/src/packlets/spaces/data-space.d.ts +2 -2
  69. package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
  70. package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts +2 -2
  71. package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts.map +1 -1
  72. package/dist/types/src/packlets/spaces/notarization-plugin.d.ts +6 -6
  73. package/dist/types/src/packlets/spaces/notarization-plugin.d.ts.map +1 -1
  74. package/dist/types/src/packlets/testing/invitation-utils.d.ts +6 -3
  75. package/dist/types/src/packlets/testing/invitation-utils.d.ts.map +1 -1
  76. package/dist/types/src/packlets/testing/test-builder.d.ts +6 -5
  77. package/dist/types/src/packlets/testing/test-builder.d.ts.map +1 -1
  78. package/dist/types/src/packlets/worker/worker-runtime.d.ts +23 -4
  79. package/dist/types/src/packlets/worker/worker-runtime.d.ts.map +1 -1
  80. package/dist/types/src/packlets/worker/worker-session.d.ts +2 -2
  81. package/dist/types/src/packlets/worker/worker-session.d.ts.map +1 -1
  82. package/dist/types/src/version.d.ts +1 -1
  83. package/dist/types/tsconfig.tsbuildinfo +1 -1
  84. package/package.json +70 -48
  85. package/src/packlets/devtools/devtools.ts +2 -2
  86. package/src/packlets/diagnostics/index.ts +1 -1
  87. package/src/packlets/identity/authenticator.ts +2 -2
  88. package/src/packlets/identity/default-space-state-machine.ts +2 -2
  89. package/src/packlets/identity/identity-manager.ts +6 -6
  90. package/src/packlets/identity/identity-recovery-manager.ts +2 -2
  91. package/src/packlets/identity/identity.ts +2 -2
  92. package/src/packlets/invitations/device-invitation-protocol.ts +2 -2
  93. package/src/packlets/invitations/invitations-handler.ts +6 -6
  94. package/src/packlets/locks/index.ts +1 -1
  95. package/src/packlets/services/client-rpc-server.ts +4 -4
  96. package/src/packlets/services/service-context.ts +30 -19
  97. package/src/packlets/services/service-host.ts +56 -16
  98. package/src/packlets/space-export/space-archive-writer.ts +3 -2
  99. package/src/packlets/spaces/data-space-manager.ts +35 -16
  100. package/src/packlets/spaces/data-space.ts +6 -5
  101. package/src/packlets/spaces/edge-feed-replicator.ts +2 -2
  102. package/src/packlets/spaces/epoch-migrations.ts +2 -2
  103. package/src/packlets/spaces/notarization-plugin.test.ts +2 -2
  104. package/src/packlets/spaces/notarization-plugin.ts +6 -6
  105. package/src/packlets/testing/invitation-utils.ts +7 -4
  106. package/src/packlets/testing/test-builder.ts +36 -10
  107. package/src/packlets/worker/worker-runtime.ts +141 -11
  108. package/src/packlets/worker/worker-session.ts +4 -4
  109. package/src/version.ts +1 -1
  110. package/dist/lib/browser/chunk-NXGWBEOK.mjs.map +0 -7
  111. package/dist/lib/node-esm/chunk-AO4R6IID.mjs.map +0 -7
@@ -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,
@@ -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,8 +78,7 @@ export class SpaceArchiveWriter extends Resource {
76
78
  const binary = this._archive.toUint8Array();
77
79
 
78
80
  return {
79
- // TODO(wittjosiah): Factor out file name construction.
80
- filename: `${new Date().toISOString()}-${this._meta.spaceId}.tar`,
81
+ filename: createFilename({ parts: [this._meta.spaceId], ext: 'tar' }),
81
82
  contents: binary,
82
83
  };
83
84
  }
@@ -16,14 +16,13 @@ import {
16
16
  getCredentialAssertion,
17
17
  } from '@dxos/credentials';
18
18
  import { Type } from '@dxos/echo';
19
- import { getTypeReference } from '@dxos/echo/internal';
19
+ import { getSchemaDXN } from '@dxos/echo/internal';
20
20
  import {
21
21
  AuthStatus,
22
22
  CredentialServerExtension,
23
23
  DatabaseRoot,
24
24
  type EchoEdgeReplicator,
25
25
  type EchoHost,
26
- FIND_PARAMS,
27
26
  type MeshEchoReplicator,
28
27
  type MetadataStore,
29
28
  type Space,
@@ -34,10 +33,10 @@ import {
34
33
  } from '@dxos/echo-pipeline';
35
34
  import {
36
35
  type DatabaseDirectory,
36
+ EncodedReference,
37
37
  type ObjectStructure,
38
38
  SpaceDocVersion,
39
39
  createIdFromSpaceKey,
40
- encodeReference,
41
40
  } from '@dxos/echo-protocol';
42
41
  import type { EdgeConnection, EdgeHttpClient } from '@dxos/edge-client';
43
42
  import { type FeedStore, writeMessages } from '@dxos/feed-store';
@@ -105,7 +104,7 @@ export type AdmitMemberOptions = {
105
104
  delegationCredentialId?: PublicKey;
106
105
  };
107
106
 
108
- export type DataSpaceManagerParams = {
107
+ export type DataSpaceManagerProps = {
109
108
  spaceManager: SpaceManager;
110
109
  metadataStore: MetadataStore;
111
110
  keyring: Keyring;
@@ -117,15 +116,20 @@ export type DataSpaceManagerParams = {
117
116
  edgeHttpClient?: EdgeHttpClient;
118
117
  meshReplicator?: MeshEchoReplicator;
119
118
  echoEdgeReplicator?: EchoEdgeReplicator;
120
- runtimeParams?: DataSpaceManagerRuntimeParams;
119
+ runtimeProps?: DataSpaceManagerRuntimeProps;
121
120
  edgeFeatures?: Runtime.Client.EdgeFeatures;
122
121
  };
123
122
 
124
- export type DataSpaceManagerRuntimeParams = {
123
+ export type DataSpaceManagerRuntimeProps = {
125
124
  spaceMemberPresenceAnnounceInterval?: number;
126
125
  spaceMemberPresenceOfflineTimeout?: number;
127
126
  activeEdgeNotarizationPollingInterval?: number;
128
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;
129
133
  };
130
134
 
131
135
  export type CreateSpaceOptions = {
@@ -153,9 +157,9 @@ export class DataSpaceManager extends Resource {
153
157
  private readonly _edgeFeatures?: Runtime.Client.EdgeFeatures = undefined;
154
158
  private readonly _meshReplicator?: MeshEchoReplicator = undefined;
155
159
  private readonly _echoEdgeReplicator?: EchoEdgeReplicator = undefined;
156
- private readonly _runtimeParams?: DataSpaceManagerRuntimeParams = undefined;
160
+ private readonly _runtimeProps?: DataSpaceManagerRuntimeProps = undefined;
157
161
 
158
- constructor(params: DataSpaceManagerParams) {
162
+ constructor(params: DataSpaceManagerProps) {
159
163
  super();
160
164
 
161
165
  this._spaceManager = params.spaceManager;
@@ -170,7 +174,7 @@ export class DataSpaceManager extends Resource {
170
174
  this._edgeFeatures = params.edgeFeatures;
171
175
  this._echoEdgeReplicator = params.echoEdgeReplicator;
172
176
  this._edgeHttpClient = params.edgeHttpClient;
173
- this._runtimeParams = params.runtimeParams;
177
+ this._runtimeProps = params.runtimeProps;
174
178
 
175
179
  trace.diagnostic({
176
180
  id: 'spaces',
@@ -180,7 +184,7 @@ export class DataSpaceManager extends Resource {
180
184
  Array.from(this._spaces.values()).map(async (space) => {
181
185
  const rootUrl = space.automergeSpaceState.rootUrl;
182
186
  const rootHandle = rootUrl
183
- ? await this._echoHost.automergeRepo.find<Doc<DatabaseDirectory>>(rootUrl as AutomergeUrl, FIND_PARAMS)
187
+ ? await this._echoHost.loadDoc<Doc<DatabaseDirectory>>(Context.default(), rootUrl as AutomergeUrl)
184
188
  : undefined;
185
189
  await rootHandle?.whenReady();
186
190
  const rootDoc = rootHandle?.doc();
@@ -218,15 +222,28 @@ export class DataSpaceManager extends Resource {
218
222
  log.trace('dxos.echo.data-space-manager.open', Trace.begin({ id: this._instanceId }));
219
223
  log('metadata loaded', { spaces: this._metadataStore.spaces.length });
220
224
 
225
+ const spacesToActivate: DataSpace[] = [];
221
226
  await forEachAsync(this._metadataStore.spaces, async (spaceMetadata) => {
222
227
  try {
223
228
  log('load space', { spaceMetadata });
224
- 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
+ }
225
234
  } catch (err) {
226
235
  log.error('Error loading space', { spaceMetadata, err });
227
236
  }
228
237
  });
229
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
+
230
247
  this.updated.emit();
231
248
 
232
249
  log.trace('dxos.echo.data-space-manager.open', Trace.end({ id: this._instanceId }));
@@ -366,7 +383,7 @@ export class DataSpaceManager extends Resource {
366
383
  // TODO(dmaretskyi): Better API for low-level data access.
367
384
  const properties: ObjectStructure = {
368
385
  system: {
369
- type: encodeReference(getTypeReference(SpaceProperties)!),
386
+ type: EncodedReference.fromDXN(getSchemaDXN(SpaceProperties)!),
370
387
  },
371
388
  data: {
372
389
  [DEFAULT_SPACE_KEY]: this._signingContext.identityKey.toHex(),
@@ -388,7 +405,9 @@ export class DataSpaceManager extends Resource {
388
405
  private async _getSpaceRootDocument(space: DataSpace): Promise<DocHandle<DatabaseDirectory>> {
389
406
  const automergeIndex = space.automergeSpaceState.rootUrl;
390
407
  invariant(automergeIndex);
391
- 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
+ });
392
411
  await document.whenReady();
393
412
  return document;
394
413
  }
@@ -500,8 +519,8 @@ export class DataSpaceManager extends Resource {
500
519
  localPeerId: this._signingContext.deviceKey,
501
520
  });
502
521
  const presence = new Presence({
503
- announceInterval: this._runtimeParams?.spaceMemberPresenceAnnounceInterval ?? PRESENCE_ANNOUNCE_INTERVAL,
504
- offlineTimeout: this._runtimeParams?.spaceMemberPresenceOfflineTimeout ?? PRESENCE_OFFLINE_TIMEOUT,
522
+ announceInterval: this._runtimeProps?.spaceMemberPresenceAnnounceInterval ?? PRESENCE_ANNOUNCE_INTERVAL,
523
+ offlineTimeout: this._runtimeProps?.spaceMemberPresenceOfflineTimeout ?? PRESENCE_OFFLINE_TIMEOUT,
505
524
  identityKey: this._signingContext.identityKey,
506
525
  gossip,
507
526
  });
@@ -587,7 +606,7 @@ export class DataSpaceManager extends Resource {
587
606
  edgeConnection: this._edgeConnection,
588
607
  edgeHttpClient: this._edgeHttpClient,
589
608
  edgeFeatures: this._edgeFeatures,
590
- activeEdgeNotarizationPollingInterval: this._runtimeParams?.activeEdgeNotarizationPollingInterval,
609
+ activeEdgeNotarizationPollingInterval: this._runtimeProps?.activeEdgeNotarizationPollingInterval,
591
610
  });
592
611
  dataSpace.postOpen.append(async () => {
593
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
 
@@ -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]) => {
@@ -33,14 +33,14 @@ const WRITER_NOT_SET_ERROR_CODE = 'WRITER_NOT_SET';
33
33
 
34
34
  const credentialCodec = schema.getCodecForType('dxos.halo.credentials.Credential');
35
35
 
36
- export type NotarizationPluginParams = {
36
+ export type NotarizationPluginProps = {
37
37
  spaceId: SpaceId;
38
38
  edgeClient?: EdgeHttpClient;
39
39
  edgeFeatures?: Runtime.Client.EdgeFeatures;
40
40
  activeEdgePollingInterval?: number;
41
41
  };
42
42
 
43
- export type NotarizeParams = {
43
+ export type NotarizeProps = {
44
44
  /**
45
45
  * For cancellation.
46
46
  */
@@ -97,7 +97,7 @@ export class NotarizationPlugin extends Resource implements CredentialProcessor
97
97
 
98
98
  private readonly _edgeClient: EdgeHttpClient | undefined;
99
99
 
100
- constructor(params: NotarizationPluginParams) {
100
+ constructor(params: NotarizationPluginProps) {
101
101
  super();
102
102
  this._spaceId = params.spaceId;
103
103
  this._activeEdgePollingInterval = params.activeEdgePollingInterval ?? DEFAULT_ACTIVE_EDGE_POLLING_INTERVAL;
@@ -149,7 +149,7 @@ export class NotarizationPlugin extends Resource implements CredentialProcessor
149
149
  retryTimeout = DEFAULT_RETRY_TIMEOUT,
150
150
  successDelay = DEFAULT_SUCCESS_DELAY,
151
151
  edgeRetryJitter,
152
- }: NotarizeParams): Promise<void> {
152
+ }: NotarizeProps): Promise<void> {
153
153
  log('notarize', { credentials });
154
154
  invariant(
155
155
  credentials.every((credential) => credential.id),
@@ -399,14 +399,14 @@ const handleEdgeError = (error: any) => {
399
399
  }
400
400
  };
401
401
 
402
- export type NotarizationTeleportExtensionParams = {
402
+ export type NotarizationTeleportExtensionProps = {
403
403
  onOpen: () => Promise<void>;
404
404
  onClose: () => Promise<void>;
405
405
  onNotarize: (request: NotarizeRequest) => Promise<void>;
406
406
  };
407
407
 
408
408
  export class NotarizationTeleportExtension extends RpcExtension<Services, Services> {
409
- constructor(private readonly _params: NotarizationTeleportExtensionParams) {
409
+ constructor(private readonly _params: NotarizationTeleportExtensionProps) {
410
410
  super({
411
411
  requested: {
412
412
  NotarizationService: schema.getService('dxos.mesh.teleport.notarization.NotarizationService'),
@@ -36,15 +36,15 @@ export type PerformInvitationCallbacks<T> = {
36
36
  onError?: (value: T) => boolean | void;
37
37
  };
38
38
 
39
- export type PerformInvitationParams = {
39
+ export type PerformInvitationProps = {
40
40
  host: ServiceContext | InvitationHost;
41
41
  guest: ServiceContext | InvitationGuest;
42
+ guestDeviceProfile?: DeviceProfileDocument;
42
43
  options?: Partial<Invitation>;
43
44
  hooks?: {
44
45
  host?: PerformInvitationCallbacks<CancellableInvitation>;
45
46
  guest?: PerformInvitationCallbacks<AuthenticatingInvitation>;
46
47
  };
47
- guestDeviceProfile?: DeviceProfileDocument;
48
48
  codeInputDelay?: number;
49
49
  };
50
50
 
@@ -52,14 +52,17 @@ export type Result = { invitation?: Invitation; error?: Error };
52
52
 
53
53
  // TODO(burdon): Make async.
54
54
  // TODO(burdon): Rename startInvitation.
55
+ /**
56
+ *
57
+ */
55
58
  export const performInvitation = ({
56
59
  host,
57
60
  guest,
61
+ guestDeviceProfile,
58
62
  options,
59
63
  hooks,
60
- guestDeviceProfile,
61
64
  codeInputDelay,
62
- }: PerformInvitationParams): [Promise<Result>, Promise<Result>] => {
65
+ }: PerformInvitationProps): [Promise<Result>, Promise<Result>] => {
63
66
  let guestError = false;
64
67
  let guestConnected = false;
65
68
  let wereConnected = false;
@@ -2,6 +2,10 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
+ import * as Reactivity from '@effect/experimental/Reactivity';
6
+ import * as Layer from 'effect/Layer';
7
+ import * as ManagedRuntime from 'effect/ManagedRuntime';
8
+
5
9
  import { type Config } from '@dxos/config';
6
10
  import { Context } from '@dxos/context';
7
11
  import { CredentialGenerator, createCredentialSignerWithChain } from '@dxos/credentials';
@@ -15,11 +19,13 @@ import { MemorySignalManager, MemorySignalManagerContext, type SignalManager } f
15
19
  import { MemoryTransportFactory, SwarmNetworkManager } from '@dxos/network-manager';
16
20
  import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
17
21
  import { type Storage, StorageType, createStorage } from '@dxos/random-access-storage';
22
+ import { layerMemory as sqliteLayerMemory } from '@dxos/sql-sqlite/platform';
23
+ import * as SqlTransaction from '@dxos/sql-sqlite/SqlTransaction';
18
24
  import { BlobStore } from '@dxos/teleport-extension-object-sync';
19
25
 
20
26
  import { InvitationsHandler, InvitationsManager, SpaceInvitationProtocol } from '../invitations';
21
- import { ClientServicesHost, ServiceContext, type ServiceContextRuntimeParams } from '../services';
22
- import { DataSpaceManager, type DataSpaceManagerRuntimeParams, type SigningContext } from '../spaces';
27
+ import { ClientServicesHost, ServiceContext, type ServiceContextRuntimeProps } from '../services';
28
+ import { DataSpaceManager, type DataSpaceManagerRuntimeProps, type SigningContext } from '../spaces';
23
29
 
24
30
  //
25
31
  // TODO(burdon): Replace with test builder.
@@ -30,6 +36,11 @@ export const createServiceHost = (config: Config, signalManagerContext: MemorySi
30
36
  config,
31
37
  signalManager: new MemorySignalManager(signalManagerContext),
32
38
  transportFactory: MemoryTransportFactory,
39
+ runtime: ManagedRuntime.make(
40
+ SqlTransaction.layer
41
+ .pipe(Layer.provideMerge(sqliteLayerMemory), Layer.provideMerge(Reactivity.layer))
42
+ .pipe(Layer.orDie),
43
+ ).runtimeEffect,
33
44
  });
34
45
  };
35
46
 
@@ -39,11 +50,11 @@ export const createServiceContext = async ({
39
50
  return new MemorySignalManager(signalContext);
40
51
  },
41
52
  storage = createStorage({ type: StorageType.RAM }),
42
- runtimeParams,
53
+ runtimeProps,
43
54
  }: {
44
55
  signalManagerFactory?: () => Promise<SignalManager>;
45
56
  storage?: Storage;
46
- runtimeParams?: ServiceContextRuntimeParams;
57
+ runtimeProps?: ServiceContextRuntimeProps;
47
58
  } = {}) => {
48
59
  const signalManager = await signalManagerFactory();
49
60
  const networkManager = new SwarmNetworkManager({
@@ -53,9 +64,15 @@ export const createServiceContext = async ({
53
64
  const level = createTestLevel();
54
65
  await level.open();
55
66
 
56
- return new ServiceContext(storage, level, networkManager, signalManager, undefined, undefined, {
57
- invitationConnectionDefaultParams: { teleport: { controlHeartbeatInterval: 200 } },
58
- ...runtimeParams,
67
+ const runtime = ManagedRuntime.make(
68
+ SqlTransaction.layer
69
+ .pipe(Layer.provideMerge(sqliteLayerMemory), Layer.provideMerge(Reactivity.layer))
70
+ .pipe(Layer.orDie),
71
+ ).runtimeEffect;
72
+
73
+ return new ServiceContext(storage, level, networkManager, signalManager, undefined, undefined, runtime, {
74
+ invitationConnectionDefaultProps: { teleport: { controlHeartbeatInterval: 200 } },
75
+ ...runtimeProps,
59
76
  });
60
77
  };
61
78
 
@@ -95,7 +112,7 @@ export class TestBuilder {
95
112
 
96
113
  export type TestPeerOpts = {
97
114
  dataStore?: StorageType;
98
- dataSpaceParams?: DataSpaceManagerRuntimeParams;
115
+ dataSpaceProps?: DataSpaceManagerRuntimeProps;
99
116
  };
100
117
 
101
118
  export type TestPeerProps = {
@@ -116,6 +133,11 @@ export type TestPeerProps = {
116
133
 
117
134
  export class TestPeer {
118
135
  private _props: TestPeerProps = {};
136
+ private readonly _runtime = ManagedRuntime.make(
137
+ SqlTransaction.layer
138
+ .pipe(Layer.provideMerge(sqliteLayerMemory), Layer.provideMerge(Reactivity.layer))
139
+ .pipe(Layer.orDie),
140
+ );
119
141
 
120
142
  constructor(
121
143
  private readonly _signalContext: MemorySignalManagerContext,
@@ -179,7 +201,10 @@ export class TestPeer {
179
201
  }
180
202
 
181
203
  get echoHost() {
182
- return (this._props.echoHost ??= new EchoHost({ kv: this.level }));
204
+ return (this._props.echoHost ??= new EchoHost({
205
+ kv: this.level,
206
+ runtime: this._runtime.runtimeEffect,
207
+ }));
183
208
  }
184
209
 
185
210
  get meshEchoReplicator() {
@@ -198,7 +223,7 @@ export class TestPeer {
198
223
  edgeConnection: undefined,
199
224
  meshReplicator: this.meshEchoReplicator,
200
225
  echoEdgeReplicator: undefined,
201
- runtimeParams: this._opts.dataSpaceParams,
226
+ runtimeProps: this._opts.dataSpaceProps,
202
227
  }));
203
228
  }
204
229
 
@@ -227,6 +252,7 @@ export class TestPeer {
227
252
  async destroy(): Promise<void> {
228
253
  await this.level.close();
229
254
  await this.storage.reset();
255
+ await this._runtime.dispose();
230
256
  }
231
257
  }
232
258