@dxos/client-services 0.8.4-main.e8ec1fe → 0.8.4-main.ef1bc66f44

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 (134) 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-CZSLDMSL.mjs → chunk-NTZOEM4P.mjs} +1197 -1338
  4. package/dist/lib/browser/chunk-NTZOEM4P.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 +441 -66
  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-EUNILIU5.mjs → chunk-DQWA5ILA.mjs} +689 -699
  23. package/dist/lib/node-esm/chunk-DQWA5ILA.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 +441 -66
  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/logging/logging-service.d.ts +4 -0
  66. package/dist/types/src/packlets/logging/logging-service.d.ts.map +1 -1
  67. package/dist/types/src/packlets/services/client-rpc-server.d.ts +2 -2
  68. package/dist/types/src/packlets/services/client-rpc-server.d.ts.map +1 -1
  69. package/dist/types/src/packlets/services/feed-syncer.d.ts +41 -0
  70. package/dist/types/src/packlets/services/feed-syncer.d.ts.map +1 -0
  71. package/dist/types/src/packlets/services/platform.d.ts.map +1 -1
  72. package/dist/types/src/packlets/services/service-context.d.ts +13 -7
  73. package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
  74. package/dist/types/src/packlets/services/service-host.d.ts +19 -5
  75. package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
  76. package/dist/types/src/packlets/space-export/space-archive-writer.d.ts.map +1 -1
  77. package/dist/types/src/packlets/spaces/data-space-manager.d.ts +10 -5
  78. package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
  79. package/dist/types/src/packlets/spaces/data-space.d.ts +2 -2
  80. package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
  81. package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts +2 -2
  82. package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts.map +1 -1
  83. package/dist/types/src/packlets/spaces/notarization-plugin.d.ts +6 -6
  84. package/dist/types/src/packlets/spaces/notarization-plugin.d.ts.map +1 -1
  85. package/dist/types/src/packlets/spaces/spaces-service.d.ts.map +1 -1
  86. package/dist/types/src/packlets/testing/invitation-utils.d.ts +6 -3
  87. package/dist/types/src/packlets/testing/invitation-utils.d.ts.map +1 -1
  88. package/dist/types/src/packlets/testing/test-builder.d.ts +6 -5
  89. package/dist/types/src/packlets/testing/test-builder.d.ts.map +1 -1
  90. package/dist/types/src/packlets/worker/worker-runtime.d.ts +31 -4
  91. package/dist/types/src/packlets/worker/worker-runtime.d.ts.map +1 -1
  92. package/dist/types/src/packlets/worker/worker-session.d.ts +2 -2
  93. package/dist/types/src/packlets/worker/worker-session.d.ts.map +1 -1
  94. package/dist/types/src/version.d.ts +1 -1
  95. package/dist/types/src/version.d.ts.map +1 -1
  96. package/dist/types/tsconfig.tsbuildinfo +1 -1
  97. package/package.json +70 -48
  98. package/src/packlets/devtools/devtools.ts +2 -2
  99. package/src/packlets/diagnostics/index.ts +1 -1
  100. package/src/packlets/identity/authenticator.ts +2 -2
  101. package/src/packlets/identity/default-space-state-machine.ts +2 -2
  102. package/src/packlets/identity/identity-manager.ts +6 -6
  103. package/src/packlets/identity/identity-recovery-manager.ts +2 -2
  104. package/src/packlets/identity/identity.ts +2 -2
  105. package/src/packlets/invitations/device-invitation-protocol.ts +5 -5
  106. package/src/packlets/invitations/invitation-guest-extenstion.ts +6 -4
  107. package/src/packlets/invitations/invitation-host-extension.ts +6 -4
  108. package/src/packlets/invitations/invitation-protocol.ts +2 -3
  109. package/src/packlets/invitations/invitations-handler.ts +7 -7
  110. package/src/packlets/invitations/space-invitation-protocol.ts +7 -13
  111. package/src/packlets/locks/index.ts +1 -1
  112. package/src/packlets/logging/logging-service.ts +4 -0
  113. package/src/packlets/services/client-rpc-server.ts +4 -4
  114. package/src/packlets/services/feed-syncer.ts +227 -0
  115. package/src/packlets/services/platform.ts +7 -1
  116. package/src/packlets/services/service-context.ts +47 -21
  117. package/src/packlets/services/service-host.ts +56 -16
  118. package/src/packlets/space-export/space-archive-reader.ts +1 -1
  119. package/src/packlets/space-export/space-archive-writer.ts +3 -2
  120. package/src/packlets/spaces/data-space-manager.ts +43 -20
  121. package/src/packlets/spaces/data-space.ts +10 -6
  122. package/src/packlets/spaces/edge-feed-replicator.ts +2 -2
  123. package/src/packlets/spaces/epoch-migrations.ts +2 -2
  124. package/src/packlets/spaces/notarization-plugin.test.ts +2 -2
  125. package/src/packlets/spaces/notarization-plugin.ts +8 -8
  126. package/src/packlets/spaces/spaces-service.ts +10 -7
  127. package/src/packlets/storage/storage.ts +4 -4
  128. package/src/packlets/testing/invitation-utils.ts +7 -4
  129. package/src/packlets/testing/test-builder.ts +36 -10
  130. package/src/packlets/worker/worker-runtime.ts +149 -11
  131. package/src/packlets/worker/worker-session.ts +4 -4
  132. package/src/version.ts +1 -1
  133. package/dist/lib/browser/chunk-CZSLDMSL.mjs.map +0 -7
  134. package/dist/lib/node-esm/chunk-EUNILIU5.mjs.map +0 -7
@@ -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;
@@ -451,6 +450,9 @@ export class DataSpace {
451
450
 
452
451
  log('credentials notarized');
453
452
  } catch (err) {
453
+ if (err instanceof ContextDisposedError) {
454
+ return;
455
+ }
454
456
  log.error('error notarizing credentials for feed admission', err);
455
457
  throw err;
456
458
  }
@@ -471,7 +473,9 @@ export class DataSpace {
471
473
  await warnAfterTimeout(5_000, 'Automerge root doc load timeout (DataSpace)', async () => {
472
474
  handle = await cancelWithContext(
473
475
  this._ctx,
474
- this._echoHost.automergeRepo.find<DatabaseDirectory>(rootUrl as any, FIND_PARAMS),
476
+ this._echoHost.loadDoc<DatabaseDirectory>(Context.default(), rootUrl as AutomergeUrl, {
477
+ fetchFromNetwork: true,
478
+ }),
475
479
  );
476
480
  await cancelWithContext(this._ctx, handle.whenReady());
477
481
  });
@@ -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),
@@ -392,21 +392,21 @@ export class NotarizationPlugin extends Resource implements CredentialProcessor
392
392
  }
393
393
 
394
394
  const handleEdgeError = (error: any) => {
395
- if (!(error instanceof EdgeCallFailedError) || error.errorData) {
395
+ if (!(error instanceof EdgeCallFailedError) || error.data) {
396
396
  log.catch(error);
397
397
  } else {
398
- log.info('Edge notarization failure', { reason: error.reason });
398
+ log.info('Edge notarization failure', { message: error.message });
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'),
@@ -88,7 +88,7 @@ export class SpacesServiceImpl implements SpacesService {
88
88
  await space.deactivate();
89
89
  break;
90
90
  default:
91
- throw new ApiError('Invalid space state');
91
+ throw new ApiError({ message: 'Invalid space state' });
92
92
  }
93
93
  }
94
94
 
@@ -104,9 +104,12 @@ export class SpacesServiceImpl implements SpacesService {
104
104
  throw new SpaceNotFoundError(request.spaceKey);
105
105
  }
106
106
  if (!space.spaceState.hasMembershipManagementPermission(identity.identityKey)) {
107
- throw new AuthorizationError('No member management permission.', {
108
- spaceKey: space.key,
109
- role: space.spaceState.getMemberRole(identity.identityKey),
107
+ throw new AuthorizationError({
108
+ message: 'No member management permission.',
109
+ context: {
110
+ spaceKey: space.key,
111
+ role: space.spaceState.getMemberRole(identity.identityKey),
112
+ },
110
113
  });
111
114
  }
112
115
  const credentials = await createAdmissionCredentials(
@@ -368,9 +371,9 @@ export class SpacesServiceImpl implements SpacesService {
368
371
 
369
372
  private _requireIdentity() {
370
373
  if (!this._identityManager.identity) {
371
- throw new IdentityNotInitializedError(
372
- 'This device has no HALO identity available. See https://docs.dxos.org/guide/platform/halo',
373
- );
374
+ throw new IdentityNotInitializedError({
375
+ message: 'This device has no HALO identity available. See https://docs.dxos.org/guide/platform/halo',
376
+ });
374
377
  }
375
378
  return this._identityManager.identity;
376
379
  }
@@ -14,16 +14,16 @@ import StorageDriver = Runtime.Client.Storage.StorageDriver;
14
14
  export const createStorageObjects = (config: Runtime.Client.Storage) => {
15
15
  const { persistent = false, keyStore, dataStore } = config ?? {};
16
16
  if (persistent && dataStore === StorageDriver.RAM) {
17
- throw new InvalidConfigError('RAM storage cannot be used in persistent mode.');
17
+ throw new InvalidConfigError({ message: 'RAM storage cannot be used in persistent mode.' });
18
18
  }
19
19
  if (!persistent && dataStore !== undefined && dataStore !== StorageDriver.RAM) {
20
- throw new InvalidConfigError('Cannot use a persistent storage in not persistent mode.');
20
+ throw new InvalidConfigError({ message: 'Cannot use a persistent storage in not persistent mode.' });
21
21
  }
22
22
  if (persistent && keyStore === StorageDriver.RAM) {
23
- throw new InvalidConfigError('RAM key storage cannot be used in persistent mode.');
23
+ throw new InvalidConfigError({ message: 'RAM key storage cannot be used in persistent mode.' });
24
24
  }
25
25
  if (!persistent && keyStore !== StorageDriver.RAM && keyStore !== undefined) {
26
- throw new InvalidConfigError('Cannot use a persistent key storage in not persistent mode.');
26
+ throw new InvalidConfigError({ message: 'Cannot use a persistent key storage in not persistent mode.' });
27
27
  }
28
28
 
29
29
  return {
@@ -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