@dxos/client-services 0.4.9-main.a108ade → 0.4.9-main.a3cfaa7

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 (53) hide show
  1. package/dist/lib/browser/{chunk-565CLS7S.mjs → chunk-2YG3XNTV.mjs} +207 -279
  2. package/dist/lib/browser/chunk-2YG3XNTV.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +1 -3
  4. package/dist/lib/browser/index.mjs.map +1 -1
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/packlets/testing/index.mjs +6 -15
  7. package/dist/lib/browser/packlets/testing/index.mjs.map +3 -3
  8. package/dist/lib/node/{chunk-WKOJPBHT.cjs → chunk-WBOCFJUB.cjs} +223 -296
  9. package/dist/lib/node/chunk-WBOCFJUB.cjs.map +7 -0
  10. package/dist/lib/node/index.cjs +37 -39
  11. package/dist/lib/node/index.cjs.map +1 -1
  12. package/dist/lib/node/meta.json +1 -1
  13. package/dist/lib/node/packlets/testing/index.cjs +8 -17
  14. package/dist/lib/node/packlets/testing/index.cjs.map +3 -3
  15. package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts.map +1 -1
  16. package/dist/types/src/packlets/services/diagnostics.d.ts +1 -1
  17. package/dist/types/src/packlets/services/diagnostics.d.ts.map +1 -1
  18. package/dist/types/src/packlets/services/service-context.d.ts +3 -6
  19. package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
  20. package/dist/types/src/packlets/services/service-host.d.ts +1 -5
  21. package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
  22. package/dist/types/src/packlets/spaces/automerge-space-state.d.ts +3 -0
  23. package/dist/types/src/packlets/spaces/automerge-space-state.d.ts.map +1 -1
  24. package/dist/types/src/packlets/spaces/data-space-manager.d.ts +2 -3
  25. package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
  26. package/dist/types/src/packlets/spaces/data-space.d.ts +5 -3
  27. package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
  28. package/dist/types/src/packlets/spaces/spaces-service.d.ts +2 -3
  29. package/dist/types/src/packlets/spaces/spaces-service.d.ts.map +1 -1
  30. package/dist/types/src/packlets/testing/test-builder.d.ts +2 -6
  31. package/dist/types/src/packlets/testing/test-builder.d.ts.map +1 -1
  32. package/dist/types/src/version.d.ts +1 -1
  33. package/package.json +34 -37
  34. package/src/packlets/identity/identity-manager.test.ts +0 -2
  35. package/src/packlets/identity/identity.test.ts +0 -4
  36. package/src/packlets/indexing/util.ts +2 -2
  37. package/src/packlets/invitations/space-invitation-protocol.test.ts +3 -12
  38. package/src/packlets/invitations/space-invitation-protocol.ts +0 -1
  39. package/src/packlets/services/automerge-host.test.ts +2 -5
  40. package/src/packlets/services/diagnostics.ts +5 -44
  41. package/src/packlets/services/service-context.test.ts +3 -76
  42. package/src/packlets/services/service-context.ts +5 -18
  43. package/src/packlets/services/service-host.ts +6 -23
  44. package/src/packlets/spaces/automerge-space-state.ts +9 -0
  45. package/src/packlets/spaces/data-space-manager.test.ts +3 -145
  46. package/src/packlets/spaces/data-space-manager.ts +3 -18
  47. package/src/packlets/spaces/data-space.ts +11 -43
  48. package/src/packlets/spaces/spaces-service.test.ts +4 -9
  49. package/src/packlets/spaces/spaces-service.ts +11 -15
  50. package/src/packlets/testing/test-builder.ts +4 -26
  51. package/src/version.ts +1 -1
  52. package/dist/lib/browser/chunk-565CLS7S.mjs.map +0 -7
  53. package/dist/lib/node/chunk-WKOJPBHT.cjs.map +0 -7
@@ -24,8 +24,8 @@ export const createLoadDocuments = (automergeHost: AutomergeHost) =>
24
24
  const handle = automergeHost.repo.find(documentId as any);
25
25
  await warnAfterTimeout(5000, 'to long to load doc', () => handle.whenReady());
26
26
  const doc = handle.docSync();
27
- const heads = getHeads(doc);
28
- yield [{ id, object: doc.objects[objectId], currentHash: heads.at(-1)! }];
27
+ const hash = getHeads(doc).join('');
28
+ yield [{ id, object: doc.objects[objectId], currentHash: hash }];
29
29
  }
30
30
  };
31
31
 
@@ -6,13 +6,12 @@ import { expect } from 'chai';
6
6
 
7
7
  import { asyncChain, Trigger } from '@dxos/async';
8
8
  import { raise } from '@dxos/debug';
9
- import { testLocalDatabase } from '@dxos/echo-pipeline/testing';
10
9
  import { AlreadyJoinedError } from '@dxos/protocols';
11
10
  import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
12
11
  import { afterTest, describe, test } from '@dxos/test';
13
12
 
14
13
  import { type ServiceContext } from '../services';
15
- import { createIdentity, createPeers, syncItemsLocal } from '../testing';
14
+ import { createIdentity, createPeers } from '../testing';
16
15
  import { performInvitation } from '../testing/invitation-utils';
17
16
 
18
17
  const closeAfterTest = async (peer: ServiceContext) => {
@@ -40,14 +39,6 @@ describe('services/space-invitations-protocol', () => {
40
39
  await space.close();
41
40
  });
42
41
 
43
- test('genesis with database mutations', async () => {
44
- const [peer] = await asyncChain<ServiceContext>([createIdentity, closeAfterTest])(createPeers(1));
45
- const space = await peer.dataSpaceManager!.createSpace();
46
- afterTest(() => space.close());
47
-
48
- await testLocalDatabase(space.dataPipeline);
49
- });
50
-
51
42
  test('invitation with no auth', async () => {
52
43
  const [host, guest] = await asyncChain<ServiceContext>([createIdentity, closeAfterTest])(createPeers(2));
53
44
 
@@ -65,7 +56,7 @@ describe('services/space-invitations-protocol', () => {
65
56
  await host.dataSpaceManager?.waitUntilSpaceReady(space1.key);
66
57
  await guest.dataSpaceManager?.waitUntilSpaceReady(space2.key);
67
58
 
68
- await syncItemsLocal(space1.dataPipeline, space2.dataPipeline);
59
+ await space2.inner.controlPipeline.state.waitUntilTimeframe(space1.inner.controlPipeline.state.timeframe);
69
60
 
70
61
  await space1.close();
71
62
  await space2.close();
@@ -149,7 +140,7 @@ describe('services/space-invitations-protocol', () => {
149
140
  await host.dataSpaceManager?.waitUntilSpaceReady(space1.key);
150
141
  await guest.dataSpaceManager?.waitUntilSpaceReady(space2.key);
151
142
 
152
- await syncItemsLocal(space1.dataPipeline, space2.dataPipeline);
143
+ await space2.inner.controlPipeline.state.waitUntilTimeframe(space1.inner.controlPipeline.state.timeframe);
153
144
 
154
145
  await space1.close();
155
146
  await space2.close();
@@ -72,7 +72,6 @@ export class SpaceInvitationProtocol implements InvitationProtocol {
72
72
  space: {
73
73
  credential: spaceMemberCredential,
74
74
  controlTimeframe: space.inner.controlPipeline.state.timeframe,
75
- dataTimeframe: space.dataPipeline.pipelineState?.timeframe,
76
75
  },
77
76
  };
78
77
  }
@@ -5,7 +5,7 @@
5
5
  import { expect } from 'chai';
6
6
 
7
7
  import { asyncTimeout, sleep } from '@dxos/async';
8
- import { AutomergeHost, DataServiceImpl, type DataServiceSubscriptions } from '@dxos/echo-pipeline';
8
+ import { AutomergeHost, DataServiceImpl } from '@dxos/echo-pipeline';
9
9
  import { AutomergeContext } from '@dxos/echo-schema';
10
10
  import { StorageType, createStorage } from '@dxos/random-access-storage';
11
11
  import { afterTest, describe, test } from '@dxos/test';
@@ -23,10 +23,7 @@ describe('AutomergeHost', () => {
23
23
 
24
24
  const host = new AutomergeHost({ directory: storageDirectory });
25
25
  afterTest(() => host.close());
26
- const dataService = new DataServiceImpl(
27
- {} as DataServiceSubscriptions, // is not used in this test, just required argument
28
- host,
29
- );
26
+ const dataService = new DataServiceImpl(host);
30
27
  const client = new AutomergeContext(dataService);
31
28
  afterTest(() => client.close());
32
29
 
@@ -6,21 +6,18 @@ import { type ClientServices } from '@dxos/client-protocol';
6
6
  import { getFirstStreamValue } from '@dxos/codec-protobuf';
7
7
  import { type Config, type ConfigProto } from '@dxos/config';
8
8
  import { credentialTypeFilter } from '@dxos/credentials';
9
- import { DocumentModel, type DocumentModelState } from '@dxos/document-model';
10
- import { TYPE_PROPERTIES } from '@dxos/echo-db';
11
9
  import { invariant } from '@dxos/invariant';
12
10
  import { type PublicKey } from '@dxos/keys';
13
- import { log } from '@dxos/log';
14
11
  import { STORAGE_VERSION } from '@dxos/protocols';
15
12
  import {
13
+ SpaceMember,
16
14
  type Device,
17
15
  type Identity,
16
+ type LogEntry,
18
17
  type Metrics,
19
18
  type NetworkStatus,
20
- type Space as SpaceProto,
21
19
  type Platform,
22
- SpaceMember,
23
- type LogEntry,
20
+ type Space as SpaceProto,
24
21
  } from '@dxos/protocols/proto/dxos/client/services';
25
22
  import { type SubscribeToFeedsResponse } from '@dxos/protocols/proto/dxos/devtools/host';
26
23
  import { type SwarmInfo } from '@dxos/protocols/proto/dxos/devtools/swarm';
@@ -180,25 +177,6 @@ export const createDiagnostics = async (
180
177
  return diagnostics;
181
178
  };
182
179
 
183
- const getProperties = (space: DataSpace) => {
184
- let properties: any = {};
185
- try {
186
- // Add properties to cache.
187
- const propertiesItem = space.dataPipeline.itemManager.items.find(
188
- (item) =>
189
- item.modelMeta?.type === DocumentModel.meta.type &&
190
- (item.state as DocumentModelState)?.type?.itemId === TYPE_PROPERTIES,
191
- );
192
-
193
- const state = propertiesItem?.state as DocumentModelState;
194
- properties = state?.data;
195
- } catch (err: any) {
196
- log.warn(err.message);
197
- }
198
-
199
- return properties;
200
- };
201
-
202
180
  const getSpaceStats = async (space: DataSpace): Promise<SpaceStats> => {
203
181
  const stats: SpaceStats = {
204
182
  key: space.key,
@@ -226,33 +204,16 @@ const getSpaceStats = async (space: DataSpace): Promise<SpaceStats> => {
226
204
 
227
205
  pipeline: {
228
206
  // TODO(burdon): Pick properties from credentials if needed.
229
- // currentEpoch: space.dataPipeline.currentEpoch,
230
- // appliedEpoch: space.dataPipeline.appliedEpoch,
207
+ currentEpoch: space.automergeSpaceState.lastEpoch,
208
+ appliedEpoch: space.automergeSpaceState.lastEpoch,
231
209
 
232
210
  controlFeeds: space.inner.controlPipeline.state.feeds.map((feed) => feed.key),
233
211
  currentControlTimeframe: space.inner.controlPipeline.state.timeframe,
234
212
  targetControlTimeframe: space.inner.controlPipeline.state.targetTimeframe,
235
213
  totalControlTimeframe: space.inner.controlPipeline.state.endTimeframe,
236
-
237
- // TODO(burdon): Empty?
238
- dataFeeds: space.dataPipeline.pipelineState?.feeds.map((feed) => feed.key) ?? [],
239
- startDataTimeframe: space.dataPipeline.pipelineState?.startTimeframe,
240
- currentDataTimeframe: space.dataPipeline.pipelineState?.timeframe,
241
- targetDataTimeframe: space.dataPipeline.pipelineState?.targetTimeframe,
242
- totalDataTimeframe: space.dataPipeline.pipelineState?.endTimeframe,
243
214
  },
244
215
  };
245
216
 
246
- // TODO(burdon): May not be open?
247
- if (space.dataPipeline.itemManager) {
248
- Object.assign(stats, {
249
- properties: getProperties(space),
250
- db: {
251
- objects: space.dataPipeline.itemManager.entities.size,
252
- },
253
- } as SpaceStats);
254
- }
255
-
256
217
  // TODO(burdon): Factor out.
257
218
  if (stats.metrics) {
258
219
  const { open, ready } = stats.metrics;
@@ -2,87 +2,14 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { expect } from 'chai';
6
-
7
- import { DocumentModel, type DocumentModelState, MutationBuilder } from '@dxos/document-model';
8
- import { createModelMutation, encodeModelMutation, genesisMutation } from '@dxos/echo-db';
9
- import { type WriteReceipt } from '@dxos/feed-store';
10
- import { PublicKey } from '@dxos/keys';
11
- import { log } from '@dxos/log';
12
5
  import { MemorySignalManagerContext } from '@dxos/messaging';
13
6
  import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
14
7
  import { describe, test } from '@dxos/test';
15
- import { Timeframe } from '@dxos/timeframe';
16
- import { range } from '@dxos/util';
17
8
 
18
- import { createServiceContext, syncItemsLocal } from '../testing';
9
+ import { createServiceContext } from '../testing';
19
10
  import { performInvitation } from '../testing/invitation-utils';
20
11
 
21
12
  describe('services/ServiceContext', () => {
22
- test('existing space is synchronized on device invitations', async () => {
23
- const networkContext = new MemorySignalManagerContext();
24
- const device1 = createServiceContext({ signalContext: networkContext });
25
- await device1.createIdentity();
26
- const space1 = await device1.dataSpaceManager!.createSpace();
27
-
28
- const itemId = PublicKey.random().toHex();
29
- await space1.dataPipeline.databaseHost!.getWriteStream()?.write({
30
- batch: genesisMutation(itemId, DocumentModel.meta.type),
31
- });
32
-
33
- let counter = 0;
34
-
35
- for (const _ in range(5)) {
36
- const receipts: WriteReceipt[] = [];
37
- for (const _ in range(50)) {
38
- receipts.push(
39
- await space1.dataPipeline.databaseHost!.getWriteStream()!.write({
40
- batch: createModelMutation(
41
- itemId,
42
- encodeModelMutation(DocumentModel.meta, new MutationBuilder().set('counter', ++counter).build()),
43
- ),
44
- }),
45
- );
46
- }
47
-
48
- await space1.dataPipeline.pipelineState!.waitUntilTimeframe(
49
- Timeframe.merge(...receipts.map((receipt) => new Timeframe([[receipt.feedKey, receipt.seq]]))),
50
- );
51
-
52
- await space1.createEpoch();
53
- log('epoch', { number: space1.dataPipeline.currentEpoch?.subject.assertion.number });
54
- }
55
-
56
- const device2 = createServiceContext({ signalContext: networkContext });
57
- await Promise.all(performInvitation({ host: device1, guest: device2, options: { kind: Invitation.Kind.DEVICE } }));
58
-
59
- await device2.dataSpaceManager!.waitUntilSpaceReady(space1!.key);
60
- const space2 = await device2.dataSpaceManager!.spaces.get(space1.key);
61
-
62
- log('peer 2', {
63
- currentEpoch: space2!.dataPipeline.currentEpoch?.subject.assertion.number,
64
- appliedEpoch: space2!.dataPipeline.appliedEpoch?.subject.assertion.number,
65
- });
66
-
67
- await space2?.dataPipeline.onNewEpoch.waitForCondition(
68
- () =>
69
- space2!.dataPipeline.appliedEpoch?.subject.assertion.number ===
70
- space1.dataPipeline.currentEpoch?.subject.assertion.number,
71
- );
72
-
73
- expect(space2!.dataPipeline.currentEpoch!.subject.assertion.number).to.equal(
74
- space1.dataPipeline.currentEpoch!.subject.assertion.number,
75
- );
76
- expect(space2!.dataPipeline.appliedEpoch!.subject.assertion.number).to.equal(
77
- space1.dataPipeline.appliedEpoch!.subject.assertion.number,
78
- );
79
-
80
- const item2 = space2!.dataPipeline.itemManager.entities.get(itemId);
81
- expect((item2!.state as DocumentModelState).data.counter).to.equal(counter);
82
-
83
- await syncItemsLocal(space1.dataPipeline, space2!.dataPipeline);
84
- });
85
-
86
13
  test('new space is synchronized on device invitations', async () => {
87
14
  const networkContext = new MemorySignalManagerContext();
88
15
  const device1 = createServiceContext({ signalContext: networkContext });
@@ -94,7 +21,7 @@ describe('services/ServiceContext', () => {
94
21
  const space1 = await device1.dataSpaceManager!.createSpace();
95
22
  await device2.dataSpaceManager!.waitUntilSpaceReady(space1!.key);
96
23
  const space2 = await device2.dataSpaceManager!.spaces.get(space1.key);
97
- await syncItemsLocal(space1.dataPipeline, space2!.dataPipeline);
24
+ await space2!.inner.controlPipeline.state.waitUntilTimeframe(space1.inner.controlPipeline.state.timeframe);
98
25
  }).tag('flaky');
99
26
 
100
27
  test('joined space is synchronized on device invitations', async () => {
@@ -118,6 +45,6 @@ describe('services/ServiceContext', () => {
118
45
 
119
46
  await device2.dataSpaceManager!.waitUntilSpaceReady(space1!.key);
120
47
  const space2 = await device2.dataSpaceManager!.spaces.get(space1.key);
121
- await syncItemsLocal(space1.dataPipeline, space2!.dataPipeline);
48
+ await space2!.inner.controlPipeline.state.waitUntilTimeframe(space1.inner.controlPipeline.state.timeframe);
122
49
  });
123
50
  });
@@ -4,16 +4,9 @@
4
4
 
5
5
  import { Trigger } from '@dxos/async';
6
6
  import { Context } from '@dxos/context';
7
- import { type CredentialProcessor, getCredentialAssertion } from '@dxos/credentials';
7
+ import { getCredentialAssertion, type CredentialProcessor } from '@dxos/credentials';
8
8
  import { failUndefined } from '@dxos/debug';
9
- import {
10
- valueEncoding,
11
- MetadataStore,
12
- SpaceManager,
13
- DataServiceSubscriptions,
14
- SnapshotStore,
15
- AutomergeHost,
16
- } from '@dxos/echo-pipeline';
9
+ import { AutomergeHost, MetadataStore, SnapshotStore, SpaceManager, valueEncoding } from '@dxos/echo-pipeline';
17
10
  import { FeedFactory, FeedStore } from '@dxos/feed-store';
18
11
  import { IndexMetadataStore, IndexStore, Indexer } from '@dxos/indexing';
19
12
  import { invariant } from '@dxos/invariant';
@@ -21,20 +14,19 @@ import { Keyring } from '@dxos/keyring';
21
14
  import { PublicKey } from '@dxos/keys';
22
15
  import { log } from '@dxos/log';
23
16
  import { type SignalManager } from '@dxos/messaging';
24
- import { type ModelFactory } from '@dxos/model-factory';
25
17
  import { type NetworkManager } from '@dxos/network-manager';
26
18
  import { InvalidStorageVersionError, STORAGE_VERSION, trace } from '@dxos/protocols';
27
19
  import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
28
20
  import type { FeedMessage } from '@dxos/protocols/proto/dxos/echo/feed';
29
- import { type ProfileDocument, type Credential } from '@dxos/protocols/proto/dxos/halo/credentials';
21
+ import { type Credential, type ProfileDocument } from '@dxos/protocols/proto/dxos/halo/credentials';
30
22
  import { type Storage } from '@dxos/random-access-storage';
31
23
  import { BlobStore } from '@dxos/teleport-extension-object-sync';
32
24
  import { trace as Trace } from '@dxos/tracing';
33
25
  import { safeInstanceof } from '@dxos/util';
34
26
 
35
27
  import {
36
- type CreateIdentityOptions,
37
28
  IdentityManager,
29
+ type CreateIdentityOptions,
38
30
  type IdentityManagerRuntimeParams,
39
31
  type JoinIdentityParams,
40
32
  } from '../identity';
@@ -42,8 +34,8 @@ import { createGetAllDocuments, createLoadDocuments } from '../indexing';
42
34
  import {
43
35
  DeviceInvitationProtocol,
44
36
  InvitationsHandler,
45
- type InvitationProtocol,
46
37
  SpaceInvitationProtocol,
38
+ type InvitationProtocol,
47
39
  } from '../invitations';
48
40
  import { DataSpaceManager, type DataSpaceManagerRuntimeParams, type SigningContext } from '../spaces';
49
41
 
@@ -57,7 +49,6 @@ export type ServiceContextRuntimeParams = IdentityManagerRuntimeParams & DataSpa
57
49
  @Trace.resource()
58
50
  export class ServiceContext {
59
51
  public readonly initialized = new Trigger();
60
- public readonly dataServiceSubscriptions = new DataServiceSubscriptions();
61
52
  public readonly metadataStore: MetadataStore;
62
53
  /**
63
54
  * @deprecated
@@ -89,7 +80,6 @@ export class ServiceContext {
89
80
  public readonly storage: Storage,
90
81
  public readonly networkManager: NetworkManager,
91
82
  public readonly signalManager: SignalManager,
92
- public readonly modelFactory: ModelFactory,
93
83
  public readonly _runtimeParams?: IdentityManagerRuntimeParams & DataSpaceManagerRuntimeParams,
94
84
  ) {
95
85
  // TODO(burdon): Move strings to constants.
@@ -114,7 +104,6 @@ export class ServiceContext {
114
104
  networkManager: this.networkManager,
115
105
  blobStore: this.blobStore,
116
106
  metadataStore: this.metadataStore,
117
- modelFactory: this.modelFactory,
118
107
  snapshotStore: this.snapshotStore,
119
108
  });
120
109
 
@@ -186,7 +175,6 @@ export class ServiceContext {
186
175
  await this.feedStore.close();
187
176
  await this.networkManager.close();
188
177
  await this.signalManager.close();
189
- this.dataServiceSubscriptions.clear();
190
178
  await this.metadataStore.close();
191
179
  await this.indexer.destroy();
192
180
  log('closed');
@@ -246,7 +234,6 @@ export class ServiceContext {
246
234
  this.dataSpaceManager = new DataSpaceManager(
247
235
  this.spaceManager,
248
236
  this.metadataStore,
249
- this.dataServiceSubscriptions,
250
237
  this.keyring,
251
238
  signingContext,
252
239
  this.feedStore,
@@ -3,23 +3,20 @@
3
3
  //
4
4
 
5
5
  import { Event, synchronized } from '@dxos/async';
6
- import { clientServiceBundle, type ClientServices, defaultKey, Properties } from '@dxos/client-protocol';
6
+ import { Properties, clientServiceBundle, defaultKey, type ClientServices } from '@dxos/client-protocol';
7
7
  import { type Config } from '@dxos/config';
8
8
  import { Context } from '@dxos/context';
9
- import { DocumentModel } from '@dxos/document-model';
10
9
  import { DataServiceImpl } from '@dxos/echo-pipeline';
11
- import { type TypedObject, getRawDoc, type SpaceDoc, getAutomergeObjectCore } from '@dxos/echo-schema';
10
+ import { getAutomergeObjectCore, getRawDoc, type SpaceDoc, type TypedObject } from '@dxos/echo-schema';
12
11
  import { IndexServiceImpl } from '@dxos/indexing';
13
12
  import { invariant } from '@dxos/invariant';
14
13
  import { PublicKey } from '@dxos/keys';
15
14
  import { log } from '@dxos/log';
16
- import { type SignalManager, WebsocketSignalManager } from '@dxos/messaging';
17
- import { ModelFactory } from '@dxos/model-factory';
18
- import { createSimplePeerTransportFactory, NetworkManager, type TransportFactory } from '@dxos/network-manager';
15
+ import { WebsocketSignalManager, type SignalManager } from '@dxos/messaging';
16
+ import { NetworkManager, createSimplePeerTransportFactory, type TransportFactory } from '@dxos/network-manager';
19
17
  import { trace } from '@dxos/protocols';
20
18
  import { SystemStatus } from '@dxos/protocols/proto/dxos/client/services';
21
19
  import { type Storage } from '@dxos/random-access-storage';
22
- import { TextModel } from '@dxos/text-model';
23
20
  import { TRACE_PROCESSOR, trace as Trace } from '@dxos/tracing';
24
21
  import { assignDeep } from '@dxos/util';
25
22
  import { WebsocketRpcClient } from '@dxos/websocket-rpc';
@@ -28,7 +25,7 @@ import { createDiagnostics } from './diagnostics';
28
25
  import { ServiceContext, type ServiceContextRuntimeParams } from './service-context';
29
26
  import { ServiceRegistry } from './service-registry';
30
27
  import { DevicesServiceImpl } from '../devices';
31
- import { DevtoolsServiceImpl, DevtoolsHostEvents } from '../devtools';
28
+ import { DevtoolsHostEvents, DevtoolsServiceImpl } from '../devtools';
32
29
  import { IdentityServiceImpl, type CreateIdentityOptions } from '../identity';
33
30
  import { InvitationsServiceImpl } from '../invitations';
34
31
  import { Lock, type ResourceLock } from '../locks';
@@ -38,17 +35,11 @@ import { SpacesServiceImpl } from '../spaces';
38
35
  import { createStorageObjects } from '../storage';
39
36
  import { SystemServiceImpl } from '../system';
40
37
 
41
- // TODO(burdon): Factor out to spaces.
42
- export const createDefaultModelFactory = () => {
43
- return new ModelFactory().registerModel(DocumentModel).registerModel(TextModel);
44
- };
45
-
46
38
  export type ClientServicesHostParams = {
47
39
  /**
48
40
  * Can be omitted if `initialize` is later called.
49
41
  */
50
42
  config?: Config;
51
- modelFactory?: ModelFactory;
52
43
  transportFactory?: TransportFactory;
53
44
  signalManager?: SignalManager;
54
45
  connectionLog?: boolean;
@@ -82,7 +73,6 @@ export class ClientServicesHost {
82
73
 
83
74
  private _config?: Config;
84
75
  private readonly _statusUpdate = new Event<void>();
85
- private readonly _modelFactory: ModelFactory;
86
76
  private _signalManager?: SignalManager;
87
77
  private _networkManager?: NetworkManager;
88
78
  private _storage?: Storage;
@@ -100,7 +90,6 @@ export class ClientServicesHost {
100
90
 
101
91
  constructor({
102
92
  config,
103
- modelFactory = createDefaultModelFactory(),
104
93
  transportFactory,
105
94
  signalManager,
106
95
  storage,
@@ -110,7 +99,6 @@ export class ClientServicesHost {
110
99
  runtimeParams,
111
100
  }: ClientServicesHostParams = {}) {
112
101
  this._storage = storage;
113
- this._modelFactory = modelFactory;
114
102
  this._callbacks = callbacks;
115
103
  this._runtimeParams = runtimeParams;
116
104
 
@@ -243,7 +231,6 @@ export class ClientServicesHost {
243
231
  this._storage,
244
232
  this._networkManager,
245
233
  this._signalManager,
246
- this._modelFactory,
247
234
  this._runtimeParams,
248
235
  );
249
236
 
@@ -268,17 +255,13 @@ export class ClientServicesHost {
268
255
  SpacesService: new SpacesServiceImpl(
269
256
  this._serviceContext.identityManager,
270
257
  this._serviceContext.spaceManager,
271
- this._serviceContext.dataServiceSubscriptions,
272
258
  async () => {
273
259
  await this._serviceContext.initialized.wait();
274
260
  return this._serviceContext.dataSpaceManager!;
275
261
  },
276
262
  ),
277
263
 
278
- DataService: new DataServiceImpl(
279
- this._serviceContext.dataServiceSubscriptions,
280
- this._serviceContext.automergeHost,
281
- ),
264
+ DataService: new DataServiceImpl(this._serviceContext.automergeHost),
282
265
 
283
266
  IndexService: new IndexServiceImpl({
284
267
  indexer: this._serviceContext.indexer,
@@ -2,6 +2,7 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
+ import { Event } from '@dxos/async';
5
6
  import { type CredentialProcessor, type SpecificCredential, checkCredentialType } from '@dxos/credentials';
6
7
  import { type Credential, type Epoch } from '@dxos/protocols/proto/dxos/halo/credentials';
7
8
 
@@ -9,6 +10,8 @@ export class AutomergeSpaceState implements CredentialProcessor {
9
10
  public rootUrl: string | undefined = undefined;
10
11
  public lastEpoch: SpecificCredential<Epoch> | undefined = undefined;
11
12
 
13
+ public readonly onNewEpoch = new Event<SpecificCredential<Epoch>>();
14
+
12
15
  private _isProcessingRootDocs = false;
13
16
 
14
17
  constructor(private readonly _onNewRoot: (rootUrl: string) => void) {}
@@ -26,6 +29,8 @@ export class AutomergeSpaceState implements CredentialProcessor {
26
29
  this._onNewRoot(this.rootUrl);
27
30
  }
28
31
  }
32
+
33
+ this.onNewEpoch.emit(credential);
29
34
  }
30
35
 
31
36
  startProcessingRootDocs() {
@@ -38,4 +43,8 @@ export class AutomergeSpaceState implements CredentialProcessor {
38
43
  }
39
44
  this._isProcessingRootDocs = true;
40
45
  }
46
+
47
+ async ensureEpochInitialized() {
48
+ await this.onNewEpoch.waitForCondition(() => !!this.lastEpoch);
49
+ }
41
50
  }