@dxos/client-services 0.6.12-main.ed7cda7 → 0.6.12-staging.0b4bb48

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 (92) hide show
  1. package/dist/lib/browser/{chunk-VENIOUQ4.mjs → chunk-YCJNCCXZ.mjs} +5115 -5208
  2. package/dist/lib/browser/chunk-YCJNCCXZ.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +3 -3
  4. package/dist/lib/browser/index.mjs.map +3 -3
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/testing/index.mjs +5 -4
  7. package/dist/lib/browser/testing/index.mjs.map +2 -2
  8. package/dist/lib/node/{chunk-US3NPCS5.cjs → chunk-Z2ZTFILR.cjs} +4897 -4990
  9. package/dist/lib/node/chunk-Z2ZTFILR.cjs.map +7 -0
  10. package/dist/lib/node/index.cjs +46 -46
  11. package/dist/lib/node/index.cjs.map +3 -3
  12. package/dist/lib/node/meta.json +1 -1
  13. package/dist/lib/node/testing/index.cjs +12 -11
  14. package/dist/lib/node/testing/index.cjs.map +2 -2
  15. package/dist/types/src/packlets/diagnostics/diagnostics-broadcast.d.ts.map +1 -1
  16. package/dist/types/src/packlets/identity/authenticator.test.d.ts +2 -0
  17. package/dist/types/src/packlets/identity/authenticator.test.d.ts.map +1 -0
  18. package/dist/types/src/packlets/identity/identity-manager.d.ts +7 -19
  19. package/dist/types/src/packlets/identity/identity-manager.d.ts.map +1 -1
  20. package/dist/types/src/packlets/identity/identity.d.ts +1 -7
  21. package/dist/types/src/packlets/identity/identity.d.ts.map +1 -1
  22. package/dist/types/src/packlets/invitations/invitation-host-extension.d.ts.map +1 -1
  23. package/dist/types/src/packlets/services/automerge-host.test.d.ts +2 -0
  24. package/dist/types/src/packlets/services/automerge-host.test.d.ts.map +1 -0
  25. package/dist/types/src/packlets/services/service-context.d.ts +4 -3
  26. package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
  27. package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
  28. package/dist/types/src/packlets/spaces/data-space-manager.d.ts +2 -1
  29. package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
  30. package/dist/types/src/packlets/spaces/data-space.d.ts +2 -1
  31. package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
  32. package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts +0 -1
  33. package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts.map +1 -1
  34. package/dist/types/src/packlets/spaces/epoch-migrations.d.ts +1 -1
  35. package/dist/types/src/packlets/spaces/epoch-migrations.d.ts.map +1 -1
  36. package/dist/types/src/packlets/storage/storage.d.ts.map +1 -1
  37. package/dist/types/src/packlets/testing/test-builder.d.ts +2 -1
  38. package/dist/types/src/packlets/testing/test-builder.d.ts.map +1 -1
  39. package/dist/types/src/packlets/worker/worker-runtime.d.ts.map +1 -1
  40. package/dist/types/src/version.d.ts +1 -1
  41. package/dist/types/src/version.d.ts.map +1 -1
  42. package/package.json +39 -43
  43. package/src/packlets/devices/devices-service.test.ts +5 -4
  44. package/src/packlets/diagnostics/diagnostics-broadcast.ts +0 -1
  45. package/src/packlets/identity/{authenticator.node.test.ts → authenticator.test.ts} +3 -2
  46. package/src/packlets/identity/identity-manager.test.ts +6 -5
  47. package/src/packlets/identity/identity-manager.ts +19 -35
  48. package/src/packlets/identity/identity-service.test.ts +8 -4
  49. package/src/packlets/identity/identity.test.ts +239 -128
  50. package/src/packlets/identity/identity.ts +8 -38
  51. package/src/packlets/invitations/device-invitation-protocol.test.ts +4 -7
  52. package/src/packlets/invitations/invitation-host-extension.ts +3 -0
  53. package/src/packlets/invitations/invitations-handler.test.ts +7 -14
  54. package/src/packlets/invitations/invitations-handler.ts +1 -1
  55. package/src/packlets/invitations/space-invitation-protocol.test.ts +3 -4
  56. package/src/packlets/logging/logging.test.ts +2 -1
  57. package/src/packlets/network/network-service.test.ts +3 -2
  58. package/src/packlets/services/automerge-host.test.ts +60 -0
  59. package/src/packlets/services/service-context.test.ts +1 -3
  60. package/src/packlets/services/service-context.ts +12 -24
  61. package/src/packlets/services/service-host.test.ts +12 -8
  62. package/src/packlets/services/service-host.ts +2 -2
  63. package/src/packlets/services/service-registry.test.ts +2 -1
  64. package/src/packlets/spaces/data-space-manager.test.ts +2 -2
  65. package/src/packlets/spaces/data-space-manager.ts +1 -4
  66. package/src/packlets/spaces/data-space.ts +2 -7
  67. package/src/packlets/spaces/edge-feed-replicator.ts +21 -59
  68. package/src/packlets/spaces/epoch-migrations.ts +2 -2
  69. package/src/packlets/spaces/notarization-plugin.test.ts +3 -2
  70. package/src/packlets/spaces/spaces-service.test.ts +9 -5
  71. package/src/packlets/storage/storage.ts +1 -0
  72. package/src/packlets/system/system-service.test.ts +2 -1
  73. package/src/packlets/testing/test-builder.ts +2 -1
  74. package/src/packlets/worker/worker-runtime.ts +2 -2
  75. package/src/version.ts +1 -1
  76. package/dist/lib/browser/chunk-VENIOUQ4.mjs.map +0 -7
  77. package/dist/lib/node/chunk-US3NPCS5.cjs.map +0 -7
  78. package/dist/lib/node-esm/chunk-LV7T6HCX.mjs +0 -7809
  79. package/dist/lib/node-esm/chunk-LV7T6HCX.mjs.map +0 -7
  80. package/dist/lib/node-esm/index.mjs +0 -416
  81. package/dist/lib/node-esm/index.mjs.map +0 -7
  82. package/dist/lib/node-esm/meta.json +0 -1
  83. package/dist/lib/node-esm/testing/index.mjs +0 -418
  84. package/dist/lib/node-esm/testing/index.mjs.map +0 -7
  85. package/dist/types/src/packlets/identity/authenticator.node.test.d.ts +0 -2
  86. package/dist/types/src/packlets/identity/authenticator.node.test.d.ts.map +0 -1
  87. package/dist/types/src/packlets/spaces/edge-feed-replicator.test.d.ts +0 -2
  88. package/dist/types/src/packlets/spaces/edge-feed-replicator.test.d.ts.map +0 -1
  89. package/dist/types/src/testing/setup.d.ts +0 -3
  90. package/dist/types/src/testing/setup.d.ts.map +0 -1
  91. package/src/packlets/spaces/edge-feed-replicator.test.ts +0 -244
  92. package/src/testing/setup.ts +0 -11
@@ -2,21 +2,20 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
- import { onTestFinished, describe, expect, test } from 'vitest';
5
+ import { expect } from 'chai';
6
6
 
7
7
  import { asyncChain, Trigger } from '@dxos/async';
8
8
  import { raise } from '@dxos/debug';
9
9
  import { AlreadyJoinedError } from '@dxos/protocols';
10
10
  import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
11
+ import { afterTest, describe, test } from '@dxos/test';
11
12
 
12
13
  import { type ServiceContext } from '../services';
13
14
  import { createIdentity, createPeers } from '../testing';
14
15
  import { acceptInvitation, createInvitation, performInvitation } from '../testing/invitation-utils';
15
16
 
16
17
  const closeAfterTest = async (peer: ServiceContext) => {
17
- onTestFinished(async () => {
18
- await peer.close();
19
- });
18
+ afterTest(() => peer.close());
20
19
  return peer;
21
20
  };
22
21
 
@@ -2,11 +2,12 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { afterEach, beforeEach, describe, expect, test } from 'vitest';
5
+ import { expect } from 'chai';
6
6
 
7
7
  import { Trigger } from '@dxos/async';
8
8
  import { log, LogLevel } from '@dxos/log';
9
9
  import { type LogEntry } from '@dxos/protocols/proto/dxos/client/services';
10
+ import { beforeEach, describe, test } from '@dxos/test';
10
11
 
11
12
  import { LoggingServiceImpl } from './logging-service';
12
13
 
@@ -2,11 +2,12 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { afterEach, onTestFinished, beforeEach, describe, expect, test } from 'vitest';
5
+ import { expect } from 'chai';
6
6
 
7
7
  import { Trigger } from '@dxos/async';
8
8
  import { Context } from '@dxos/context';
9
9
  import { type NetworkService, ConnectionState } from '@dxos/protocols/proto/dxos/client/services';
10
+ import { afterEach, afterTest, beforeEach, describe, test } from '@dxos/test';
10
11
 
11
12
  import { NetworkServiceImpl } from './network-service';
12
13
  import { type ServiceContext } from '../services';
@@ -40,7 +41,7 @@ describe('NetworkService', () => {
40
41
  query.subscribe(({ swarm }) => {
41
42
  result.wake(swarm);
42
43
  });
43
- onTestFinished(() => query.close());
44
+ afterTest(() => query.close());
44
45
  expect(await result.wait()).to.equal(ConnectionState.ONLINE);
45
46
 
46
47
  result = new Trigger<ConnectionState | undefined>();
@@ -0,0 +1,60 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import { expect } from 'chai';
6
+
7
+ import { asyncTimeout } from '@dxos/async';
8
+ import { AutomergeContext } from '@dxos/echo-db';
9
+ import { AutomergeHost, DataServiceImpl } from '@dxos/echo-pipeline';
10
+ import { IndexMetadataStore } from '@dxos/indexing';
11
+ import { createTestLevel } from '@dxos/kv-store/testing';
12
+ import { afterTest, describe, openAndClose, test } from '@dxos/test';
13
+
14
+ describe('AutomergeHost', () => {
15
+ test('automerge context is being synced with host', async () => {
16
+ //
17
+ // Setup:
18
+ // client-services | <-------------> | client
19
+ // AutomergeHost | DataServiceImpl | AutomergeContext
20
+ // creates repo and document | replicates repo | finds document in repo
21
+ //
22
+
23
+ const level = createTestLevel();
24
+ await level.open();
25
+ afterTest(() => level.close());
26
+
27
+ const host = new AutomergeHost({
28
+ db: level,
29
+ indexMetadataStore: new IndexMetadataStore({ db: level.sublevel('index-metadata') }),
30
+ });
31
+ await host.open();
32
+ afterTest(() => host.close());
33
+
34
+ const dataService = new DataServiceImpl({ automergeHost: host, updateIndexes: async () => {} });
35
+ const client = new AutomergeContext(dataService);
36
+ await openAndClose(client);
37
+
38
+ // Create document in repo.
39
+ const handle = host.repo.create();
40
+ const text = 'Hello World!';
41
+ handle.change((doc: any) => {
42
+ doc.text = text;
43
+ });
44
+
45
+ // Find document in repo.
46
+ const doc = client.repo.find<{ text: string }>(handle.url);
47
+ await asyncTimeout(doc.whenReady(), 1_000);
48
+ expect(doc.docSync().text).to.equal(text);
49
+
50
+ // Changes from client are replicated to host.
51
+ const newText = 'Goodbye World!!!';
52
+ doc.change((doc: any) => {
53
+ doc.text = newText;
54
+ });
55
+ await client.flush({ documentIds: [doc.documentId] });
56
+
57
+ await asyncTimeout(handle.whenReady(), 1_000);
58
+ expect(handle.docSync().text).to.equal(newText);
59
+ });
60
+ });
@@ -2,11 +2,9 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { describe, test } from 'vitest';
6
-
7
5
  import { MemorySignalManagerContext, MemorySignalManager } from '@dxos/messaging';
8
6
  import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
9
- import { openAndClose } from '@dxos/test-utils';
7
+ import { describe, openAndClose, test } from '@dxos/test';
10
8
 
11
9
  import { createServiceContext, performInvitation } from '../testing';
12
10
 
@@ -6,14 +6,8 @@ import { Trigger } from '@dxos/async';
6
6
  import { Context, Resource } from '@dxos/context';
7
7
  import { getCredentialAssertion, type CredentialProcessor } from '@dxos/credentials';
8
8
  import { failUndefined } from '@dxos/debug';
9
- import {
10
- EchoEdgeReplicator,
11
- EchoHost,
12
- MeshEchoReplicator,
13
- MetadataStore,
14
- SpaceManager,
15
- valueEncoding,
16
- } from '@dxos/echo-pipeline';
9
+ import { EchoEdgeReplicator, EchoHost } from '@dxos/echo-db';
10
+ import { MeshEchoReplicator, MetadataStore, SpaceManager, valueEncoding } from '@dxos/echo-pipeline';
17
11
  import type { EdgeConnection } from '@dxos/edge-client';
18
12
  import { FeedFactory, FeedStore } from '@dxos/feed-store';
19
13
  import { invariant } from '@dxos/invariant';
@@ -37,8 +31,8 @@ import { safeInstanceof } from '@dxos/util';
37
31
  import {
38
32
  IdentityManager,
39
33
  type CreateIdentityOptions,
34
+ type IdentityManagerRuntimeParams,
40
35
  type JoinIdentityParams,
41
- type IdentityManagerParams,
42
36
  } from '../identity';
43
37
  import {
44
38
  DeviceInvitationProtocol,
@@ -49,10 +43,7 @@ import {
49
43
  } from '../invitations';
50
44
  import { DataSpaceManager, type DataSpaceManagerRuntimeParams, type SigningContext } from '../spaces';
51
45
 
52
- export type ServiceContextRuntimeParams = Pick<
53
- IdentityManagerParams,
54
- 'devicePresenceOfflineTimeout' | 'devicePresenceAnnounceInterval'
55
- > &
46
+ export type ServiceContextRuntimeParams = IdentityManagerRuntimeParams &
56
47
  DataSpaceManagerRuntimeParams & {
57
48
  invitationConnectionDefaultParams?: Partial<TeleportParams>;
58
49
  disableP2pReplication?: boolean;
@@ -125,16 +116,13 @@ export class ServiceContext extends Resource {
125
116
  disableP2pReplication: this._runtimeParams?.disableP2pReplication,
126
117
  });
127
118
 
128
- this.identityManager = new IdentityManager({
129
- metadataStore: this.metadataStore,
130
- keyring: this.keyring,
131
- feedStore: this.feedStore,
132
- spaceManager: this.spaceManager,
133
- devicePresenceOfflineTimeout: this._runtimeParams?.devicePresenceOfflineTimeout,
134
- devicePresenceAnnounceInterval: this._runtimeParams?.devicePresenceAnnounceInterval,
135
- edgeConnection: this._edgeConnection,
136
- edgeFeatures: this._edgeFeatures,
137
- callbacks: {
119
+ this.identityManager = new IdentityManager(
120
+ this.metadataStore,
121
+ this.keyring,
122
+ this.feedStore,
123
+ this.spaceManager,
124
+ this._runtimeParams as IdentityManagerRuntimeParams,
125
+ {
138
126
  onIdentityConstruction: (identity) => {
139
127
  if (this._edgeConnection) {
140
128
  log.info('Setting identity on edge connection', {
@@ -153,7 +141,7 @@ export class ServiceContext extends Resource {
153
141
  }
154
142
  },
155
143
  },
156
- });
144
+ );
157
145
 
158
146
  this.echoHost = new EchoHost({ kv: this.level });
159
147
 
@@ -2,8 +2,9 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
+ import chai, { expect } from 'chai';
6
+ import chaiAsPromised from 'chai-as-promised';
5
7
  import { rmSync } from 'node:fs';
6
- import { afterEach, onTestFinished, describe, expect, test } from 'vitest';
7
8
 
8
9
  import { asyncTimeout, latch, Trigger } from '@dxos/async';
9
10
  import { Config } from '@dxos/config';
@@ -13,10 +14,13 @@ import { type PublicKey } from '@dxos/keys';
13
14
  import { MemorySignalManagerContext } from '@dxos/messaging';
14
15
  import { type Identity } from '@dxos/protocols/proto/dxos/client/services';
15
16
  import { type Credential } from '@dxos/protocols/proto/dxos/halo/credentials';
17
+ import { afterTest, describe, test } from '@dxos/test';
16
18
  import { isNode } from '@dxos/util';
17
19
 
18
20
  import { createMockCredential, createServiceHost } from '../testing';
19
21
 
22
+ chai.use(chaiAsPromised);
23
+
20
24
  describe('ClientServicesHost', () => {
21
25
  const dataRoot = '/tmp/dxos/client-services/service-host/storage';
22
26
 
@@ -34,7 +38,7 @@ describe('ClientServicesHost', () => {
34
38
  test('queryCredentials', async () => {
35
39
  const host = createServiceHost(new Config(), new MemorySignalManagerContext());
36
40
  await host.open(new Context());
37
- onTestFinished(() => host.close());
41
+ afterTest(() => host.close());
38
42
 
39
43
  await host.services.IdentityService!.createIdentity({});
40
44
  const { spaceKey } = await host.services.SpacesService!.createSpace();
@@ -45,7 +49,7 @@ describe('ClientServicesHost', () => {
45
49
  tick();
46
50
  // console.log(credential);
47
51
  });
48
- onTestFinished(() => stream.close());
52
+ afterTest(() => stream.close());
49
53
 
50
54
  await done();
51
55
  });
@@ -53,7 +57,7 @@ describe('ClientServicesHost', () => {
53
57
  test('write and query credentials', async () => {
54
58
  const host = createServiceHost(new Config(), new MemorySignalManagerContext());
55
59
  await host.open(new Context());
56
- onTestFinished(() => host.close());
60
+ afterTest(() => host.close());
57
61
 
58
62
  await host.services.IdentityService!.createIdentity({});
59
63
 
@@ -82,7 +86,7 @@ describe('ClientServicesHost', () => {
82
86
  queriedCredential.wake(credential);
83
87
  }
84
88
  });
85
- onTestFinished(() => credentials.close());
89
+ afterTest(() => credentials.close());
86
90
 
87
91
  await queriedCredential.wait();
88
92
  });
@@ -90,7 +94,7 @@ describe('ClientServicesHost', () => {
90
94
  test('sign presentation', async () => {
91
95
  const host = createServiceHost(new Config(), new MemorySignalManagerContext());
92
96
  await host.open(new Context());
93
- onTestFinished(() => host.close());
97
+ afterTest(() => host.close());
94
98
 
95
99
  await host.services.IdentityService!.createIdentity({});
96
100
 
@@ -143,9 +147,9 @@ describe('ClientServicesHost', () => {
143
147
  trigger.wake(identity.identity);
144
148
  }
145
149
  });
146
- await expect(asyncTimeout(trigger.wait(), 200)).rejects.toBeInstanceOf(Error);
150
+ await expect(asyncTimeout(trigger.wait(), 200)).to.be.rejectedWith();
147
151
  await stream?.close();
148
152
  await host.close();
149
153
  }
150
- });
154
+ }).onlyEnvironments('nodejs', 'chromium', 'firefox');
151
155
  });
@@ -15,8 +15,8 @@ import { EdgeSignalManager, WebsocketSignalManager, type SignalManager } from '@
15
15
  import {
16
16
  SwarmNetworkManager,
17
17
  createIceProvider,
18
+ createSimplePeerTransportFactory,
18
19
  type TransportFactory,
19
- createRtcTransportFactory,
20
20
  } from '@dxos/network-manager';
21
21
  import { trace } from '@dxos/protocols';
22
22
  import { SystemStatus } from '@dxos/protocols/proto/dxos/client/services';
@@ -218,7 +218,7 @@ export class ClientServicesHost {
218
218
 
219
219
  const {
220
220
  connectionLog = true,
221
- transportFactory = createRtcTransportFactory(
221
+ transportFactory = createSimplePeerTransportFactory(
222
222
  { iceServers: this._config?.get('runtime.services.ice') },
223
223
  this._config?.get('runtime.services.iceProviders') &&
224
224
  createIceProvider(this._config!.get('runtime.services.iceProviders')!),
@@ -2,7 +2,7 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
- import { describe, expect, test } from 'vitest';
5
+ import { expect } from 'chai';
6
6
 
7
7
  import { Event } from '@dxos/async';
8
8
  import { type ClientServices } from '@dxos/client-protocol';
@@ -12,6 +12,7 @@ import { log } from '@dxos/log';
12
12
  import { schema } from '@dxos/protocols/proto';
13
13
  import { type SystemService, SystemStatus } from '@dxos/protocols/proto/dxos/client/services';
14
14
  import { createLinkedPorts, createProtoRpcPeer, createServiceBundle } from '@dxos/rpc';
15
+ import { describe, test } from '@dxos/test';
15
16
 
16
17
  import { ServiceRegistry } from './service-registry';
17
18
  import { SystemServiceImpl } from '../system';
@@ -2,7 +2,7 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
- import { describe, expect, test } from 'vitest';
5
+ import { expect } from 'chai';
6
6
 
7
7
  import { asyncTimeout, latch } from '@dxos/async';
8
8
  import { createAdmissionCredentials } from '@dxos/credentials';
@@ -10,7 +10,7 @@ import { AuthStatus } from '@dxos/echo-pipeline';
10
10
  import { writeMessages } from '@dxos/feed-store';
11
11
  import { log } from '@dxos/log';
12
12
  import { SpaceState } from '@dxos/protocols/proto/dxos/client/services';
13
- import { openAndClose } from '@dxos/test-utils';
13
+ import { describe, openAndClose, test } from '@dxos/test';
14
14
 
15
15
  import { TestBuilder, type TestPeer } from '../testing';
16
16
 
@@ -14,11 +14,8 @@ import {
14
14
  type DelegateInvitationCredential,
15
15
  type MemberInfo,
16
16
  } from '@dxos/credentials';
17
+ import { convertLegacyReferences, findInlineObjectOfType, type EchoEdgeReplicator, type EchoHost } from '@dxos/echo-db';
17
18
  import {
18
- convertLegacyReferences,
19
- findInlineObjectOfType,
20
- type EchoEdgeReplicator,
21
- type EchoHost,
22
19
  AuthStatus,
23
20
  CredentialServerExtension,
24
21
  type MeshEchoReplicator,
@@ -7,13 +7,8 @@ import { AUTH_TIMEOUT } from '@dxos/client-protocol';
7
7
  import { Context, ContextDisposedError, cancelWithContext } from '@dxos/context';
8
8
  import type { SpecificCredential } from '@dxos/credentials';
9
9
  import { timed, warnAfterTimeout } from '@dxos/debug';
10
- import {
11
- type EchoHost,
12
- type DatabaseRoot,
13
- createMappedFeedWriter,
14
- type MetadataStore,
15
- type Space,
16
- } from '@dxos/echo-pipeline';
10
+ import { type EchoHost, type DatabaseRoot } from '@dxos/echo-db';
11
+ import { createMappedFeedWriter, type MetadataStore, type Space } from '@dxos/echo-pipeline';
17
12
  import { SpaceDocVersion } from '@dxos/echo-protocol';
18
13
  import type { EdgeConnection } from '@dxos/edge-client';
19
14
  import { type FeedStore, type FeedWrapper } from '@dxos/feed-store';
@@ -5,19 +5,15 @@
5
5
  import { decode as decodeCbor, encode as encodeCbor } from 'cbor-x';
6
6
 
7
7
  import { Event, Mutex, scheduleMicroTask } from '@dxos/async';
8
- import { Context, Resource } from '@dxos/context';
8
+ import { Resource, type Context } from '@dxos/context';
9
9
  import { type EdgeConnection } from '@dxos/edge-client';
10
- import { EdgeConnectionClosedError, EdgeIdentityChangedError } from '@dxos/edge-client';
11
10
  import { type FeedWrapper } from '@dxos/feed-store';
12
11
  import { invariant } from '@dxos/invariant';
13
12
  import { PublicKey, type SpaceId } from '@dxos/keys';
14
13
  import { log } from '@dxos/log';
15
14
  import { EdgeService } from '@dxos/protocols';
16
15
  import { buf } from '@dxos/protocols/buf';
17
- import {
18
- MessageSchema as RouterMessageSchema,
19
- type Message as RouterMessage,
20
- } from '@dxos/protocols/buf/dxos/edge/messenger_pb';
16
+ import { MessageSchema as RouterMessageSchema } from '@dxos/protocols/buf/dxos/edge/messenger_pb';
21
17
  import type { FeedBlock, ProtocolMessage } from '@dxos/protocols/feed-replication';
22
18
  import { ComplexMap, arrayToBuffer, bufferToArray, defaultMap, rangeFromTo } from '@dxos/util';
23
19
 
@@ -52,7 +48,7 @@ export class EdgeFeedReplicator extends Resource {
52
48
  protected override async _open(): Promise<void> {
53
49
  // TODO: handle reconnects
54
50
  this._ctx.onDispose(
55
- this._messenger.addListener((message: RouterMessage) => {
51
+ this._messenger.addListener(async (message) => {
56
52
  if (!message.serviceId) {
57
53
  return;
58
54
  }
@@ -68,43 +64,21 @@ export class EdgeFeedReplicator extends Resource {
68
64
  }
69
65
 
70
66
  const payload = decodeCbor(message.payload!.value) as ProtocolMessage;
71
- log.info('receive', { from: message.source, feedKey: payload.feedKey, type: payload.type });
67
+ log.info('recv', { from: message.source, payload });
72
68
  this._onMessage(payload);
73
69
  }),
74
70
  );
75
71
 
76
- this._messenger.connected.on(this._ctx, async () => {
77
- await this._resetConnection();
78
-
79
- this._connected = true;
80
- const connectionCtx = new Context({
81
- onError: async (err: any) => {
82
- if (connectionCtx !== this._connectionCtx) {
83
- return;
84
- }
85
- if (err instanceof EdgeIdentityChangedError || err instanceof EdgeConnectionClosedError) {
86
- log('resetting on reconnect');
87
- await this._resetConnection();
88
- } else {
89
- this._ctx.raise(err);
90
- }
91
- },
92
- });
93
- this._connectionCtx = connectionCtx;
94
- log('connection context created');
95
- scheduleMicroTask(connectionCtx, async () => {
96
- for (const feed of this._feeds.values()) {
97
- await this._replicateFeed(connectionCtx, feed);
98
- }
99
- });
100
- });
72
+ this._connected = true;
73
+ this._connectionCtx = this._ctx.derive();
74
+ for (const feed of this._feeds.values()) {
75
+ await this._replicateFeed(feed);
76
+ }
101
77
  }
102
78
 
103
79
  protected override async _close(): Promise<void> {
104
- await this._resetConnection();
105
- }
80
+ this._connected = false;
106
81
 
107
- private async _resetConnection() {
108
82
  this._connected = false;
109
83
  await this._connectionCtx?.dispose();
110
84
  this._connectionCtx = undefined;
@@ -115,8 +89,8 @@ export class EdgeFeedReplicator extends Resource {
115
89
  log.info('addFeed', { key: feed.key });
116
90
  this._feeds.set(feed.key, feed);
117
91
 
118
- if (this._connected && this._connectionCtx) {
119
- await this._replicateFeed(this._connectionCtx, feed);
92
+ if (this._connected) {
93
+ await this._replicateFeed(feed);
120
94
  }
121
95
  }
122
96
 
@@ -124,26 +98,21 @@ export class EdgeFeedReplicator extends Resource {
124
98
  return defaultMap(this._pushMutex, key, () => new Mutex());
125
99
  }
126
100
 
127
- private async _replicateFeed(ctx: Context, feed: FeedWrapper<any>) {
101
+ private async _replicateFeed(feed: FeedWrapper<any>) {
102
+ invariant(this._connectionCtx);
103
+
128
104
  await this._sendMessage({
129
105
  type: 'get-metadata',
130
106
  feedKey: feed.key.toHex(),
131
107
  });
132
108
 
133
- Event.wrap(feed.core as any, 'append').on(ctx, async () => {
109
+ Event.wrap(feed.core as any, 'append').on(this._connectionCtx, async () => {
134
110
  await this._pushBlocksIfNeeded(feed);
135
111
  });
136
112
  }
137
113
 
138
114
  private async _sendMessage(message: ProtocolMessage) {
139
- if (!this._connectionCtx) {
140
- log.info('message dropped because connection was disposed');
141
- return;
142
- }
143
-
144
- const logPayload =
145
- message.type === 'data' ? { feedKey: message.feedKey, blocks: message.blocks.map((b) => b.index) } : { message };
146
- log.info('sending message', logPayload);
115
+ log.info('sending message', { message });
147
116
 
148
117
  invariant(message.feedKey);
149
118
  const payloadValue = bufferToArray(encodeCbor(message));
@@ -161,15 +130,11 @@ export class EdgeFeedReplicator extends Resource {
161
130
  }
162
131
 
163
132
  private _onMessage(message: ProtocolMessage) {
164
- if (!this._connectionCtx) {
165
- log.warn('received message after connection context was disposed');
166
- return;
167
- }
168
- scheduleMicroTask(this._connectionCtx, async () => {
133
+ log.info('received message', { message });
134
+
135
+ scheduleMicroTask(this._ctx, async () => {
169
136
  switch (message.type) {
170
137
  case 'metadata': {
171
- log.info('received metadata', { message });
172
-
173
138
  const feedKey = PublicKey.fromHex(message.feedKey);
174
139
  const feed = this._feeds.get(feedKey);
175
140
  if (!feed) {
@@ -195,8 +160,6 @@ export class EdgeFeedReplicator extends Resource {
195
160
  }
196
161
 
197
162
  case 'data': {
198
- log.info('received data', { feed: message.feedKey, blocks: message.blocks.map((b) => b.index) });
199
-
200
163
  const feedKey = PublicKey.fromHex(message.feedKey);
201
164
  const feed = this._feeds.get(feedKey);
202
165
  if (!feed) {
@@ -260,10 +223,9 @@ export class EdgeFeedReplicator extends Resource {
260
223
  }
261
224
 
262
225
  private async _pushBlocksIfNeeded(feed: FeedWrapper<any>) {
263
- using _ = await this._getPushMutex(feed.key).acquire();
226
+ using _guard = await this._getPushMutex(feed.key).acquire();
264
227
 
265
228
  if (!this._remoteLength.has(feed.key)) {
266
- log('blocks not pushed because remote length is unknown');
267
229
  return;
268
230
  }
269
231
 
@@ -4,13 +4,13 @@
4
4
 
5
5
  import type { AutomergeUrl } from '@dxos/automerge/automerge-repo';
6
6
  import { type Context } from '@dxos/context';
7
- import { migrateDocument } from '@dxos/echo-db';
8
7
  import {
9
8
  convertLegacyReferences,
10
9
  convertLegacySpaceRootDoc,
11
10
  findInlineObjectOfType,
11
+ migrateDocument,
12
12
  type EchoHost,
13
- } from '@dxos/echo-pipeline';
13
+ } from '@dxos/echo-db';
14
14
  import { SpaceDocVersion, type SpaceDoc } from '@dxos/echo-protocol';
15
15
  import { TYPE_PROPERTIES } from '@dxos/echo-schema';
16
16
  import { invariant } from '@dxos/invariant';
@@ -2,7 +2,7 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { onTestFinished, describe, expect, test } from 'vitest';
5
+ import { expect } from 'chai';
6
6
 
7
7
  import { Context } from '@dxos/context';
8
8
  import { CredentialGenerator } from '@dxos/credentials';
@@ -11,6 +11,7 @@ import { Keyring } from '@dxos/keyring';
11
11
  import { log } from '@dxos/log';
12
12
  import { AdmittedFeed, type Credential } from '@dxos/protocols/proto/dxos/halo/credentials';
13
13
  import { TestBuilder, type TestConnection, TestPeer } from '@dxos/teleport/testing';
14
+ import { afterTest, describe, test } from '@dxos/test';
14
15
 
15
16
  import { NotarizationPlugin } from './notarization-plugin';
16
17
 
@@ -48,7 +49,7 @@ class TestAgent extends TestPeer {
48
49
  describe('NotarizationPlugin', () => {
49
50
  test('notarize single credential', async () => {
50
51
  const testBuilder = new TestBuilder();
51
- onTestFinished(() => testBuilder.destroy());
52
+ afterTest(() => testBuilder.destroy());
52
53
 
53
54
  // peer0 is there to test retries.
54
55
  const [_peer0, peer1, peer2] = await testBuilder.createPeers({ factory: () => new TestAgent() });
@@ -2,17 +2,21 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { afterEach, onTestFinished, beforeEach, describe, expect, test } from 'vitest';
5
+ import chai, { expect } from 'chai';
6
+ import chaiAsPromised from 'chai-as-promised';
6
7
 
7
8
  import { Trigger } from '@dxos/async';
8
9
  import { Context } from '@dxos/context';
9
10
  import { PublicKey } from '@dxos/keys';
10
11
  import { type Space, type SpacesService } from '@dxos/protocols/proto/dxos/client/services';
12
+ import { afterEach, afterTest, beforeEach, describe, test } from '@dxos/test';
11
13
 
12
14
  import { SpacesServiceImpl } from './spaces-service';
13
15
  import { type ServiceContext } from '../services';
14
16
  import { createServiceContext } from '../testing';
15
17
 
18
+ chai.use(chaiAsPromised);
19
+
16
20
  describe('SpacesService', () => {
17
21
  let serviceContext: ServiceContext;
18
22
  let spacesService: SpacesService;
@@ -32,7 +36,7 @@ describe('SpacesService', () => {
32
36
 
33
37
  describe('createSpace', () => {
34
38
  test('fails if no identity is available', async () => {
35
- await expect(spacesService.createSpace()).rejects.toBeInstanceOf(Error);
39
+ await expect(spacesService.createSpace()).to.be.rejectedWith();
36
40
  });
37
41
 
38
42
  test('creates a new space', async () => {
@@ -52,7 +56,7 @@ describe('SpacesService', () => {
52
56
  query.subscribe(({ spaces }) => {
53
57
  result.wake(spaces);
54
58
  });
55
- onTestFinished(() => query.close());
59
+ afterTest(() => query.close());
56
60
  expect(await result.wait()).to.be.length(0);
57
61
  });
58
62
 
@@ -69,7 +73,7 @@ describe('SpacesService', () => {
69
73
  query.subscribe(({ spaces }) => {
70
74
  result.wake(spaces);
71
75
  });
72
- onTestFinished(() => query.close());
76
+ afterTest(() => query.close());
73
77
 
74
78
  const spaces = await result.wait();
75
79
  expect(spaces).to.be.length(3);
@@ -83,7 +87,7 @@ describe('SpacesService', () => {
83
87
  query.subscribe(({ spaces }) => {
84
88
  result.wake(spaces);
85
89
  });
86
- onTestFinished(() => query.close());
90
+ afterTest(() => query.close());
87
91
  expect(await result.wait()).to.be.length(0);
88
92
 
89
93
  result.reset();
@@ -14,6 +14,7 @@ import { getRootPath } from './util';
14
14
  // TODO(burdon): Factor out.
15
15
  export const createStorageObjects = (config: Runtime.Client.Storage) => {
16
16
  const { persistent = false, keyStore, dataStore } = config ?? {};
17
+
17
18
  if (persistent && dataStore === StorageDriver.RAM) {
18
19
  throw new InvalidConfigError('RAM storage cannot be used in persistent mode.');
19
20
  }
@@ -2,11 +2,12 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { beforeEach, describe, expect, test } from 'vitest';
5
+ import { expect } from 'chai';
6
6
 
7
7
  import { Event, Trigger } from '@dxos/async';
8
8
  import { Config } from '@dxos/config';
9
9
  import { type SystemService, SystemStatus, type QueryStatusResponse } from '@dxos/protocols/proto/dxos/client/services';
10
+ import { beforeEach, describe, test } from '@dxos/test';
10
11
 
11
12
  import { SystemServiceImpl } from './system-service';
12
13