@dxos/client-services 0.6.11 → 0.6.12-main.5a87ad5

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-QYVLLBAA.mjs → chunk-5W6ZU2YY.mjs} +5154 -5061
  2. package/dist/lib/browser/chunk-5W6ZU2YY.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 +4 -5
  7. package/dist/lib/browser/testing/index.mjs.map +2 -2
  8. package/dist/lib/node/{chunk-F7G2TXVG.cjs → chunk-MQZYBWFJ.cjs} +4980 -4887
  9. package/dist/lib/node/chunk-MQZYBWFJ.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 +11 -12
  14. package/dist/lib/node/testing/index.cjs.map +2 -2
  15. package/dist/lib/node-esm/chunk-2YR6LJEW.mjs +7809 -0
  16. package/dist/lib/node-esm/chunk-2YR6LJEW.mjs.map +7 -0
  17. package/dist/lib/node-esm/index.mjs +416 -0
  18. package/dist/lib/node-esm/index.mjs.map +7 -0
  19. package/dist/lib/node-esm/meta.json +1 -0
  20. package/dist/lib/node-esm/testing/index.mjs +418 -0
  21. package/dist/lib/node-esm/testing/index.mjs.map +7 -0
  22. package/dist/types/src/packlets/diagnostics/diagnostics-broadcast.d.ts.map +1 -1
  23. package/dist/types/src/packlets/identity/authenticator.node.test.d.ts +2 -0
  24. package/dist/types/src/packlets/identity/authenticator.node.test.d.ts.map +1 -0
  25. package/dist/types/src/packlets/identity/identity-manager.d.ts +19 -7
  26. package/dist/types/src/packlets/identity/identity-manager.d.ts.map +1 -1
  27. package/dist/types/src/packlets/identity/identity.d.ts +7 -1
  28. package/dist/types/src/packlets/identity/identity.d.ts.map +1 -1
  29. package/dist/types/src/packlets/invitations/invitation-host-extension.d.ts.map +1 -1
  30. package/dist/types/src/packlets/services/service-context.d.ts +3 -4
  31. package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
  32. package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
  33. package/dist/types/src/packlets/spaces/data-space-manager.d.ts +1 -2
  34. package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
  35. package/dist/types/src/packlets/spaces/data-space.d.ts +1 -2
  36. package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
  37. package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts +1 -0
  38. package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts.map +1 -1
  39. package/dist/types/src/packlets/spaces/edge-feed-replicator.test.d.ts +2 -0
  40. package/dist/types/src/packlets/spaces/edge-feed-replicator.test.d.ts.map +1 -0
  41. package/dist/types/src/packlets/spaces/epoch-migrations.d.ts +1 -1
  42. package/dist/types/src/packlets/spaces/epoch-migrations.d.ts.map +1 -1
  43. package/dist/types/src/packlets/storage/storage.d.ts.map +1 -1
  44. package/dist/types/src/packlets/testing/test-builder.d.ts +1 -2
  45. package/dist/types/src/packlets/testing/test-builder.d.ts.map +1 -1
  46. package/dist/types/src/packlets/worker/worker-runtime.d.ts.map +1 -1
  47. package/dist/types/src/testing/setup.d.ts +3 -0
  48. package/dist/types/src/testing/setup.d.ts.map +1 -0
  49. package/dist/types/src/version.d.ts +1 -1
  50. package/dist/types/src/version.d.ts.map +1 -1
  51. package/package.json +43 -39
  52. package/src/packlets/devices/devices-service.test.ts +4 -5
  53. package/src/packlets/diagnostics/diagnostics-broadcast.ts +1 -0
  54. package/src/packlets/identity/{authenticator.test.ts → authenticator.node.test.ts} +2 -3
  55. package/src/packlets/identity/identity-manager.test.ts +5 -6
  56. package/src/packlets/identity/identity-manager.ts +35 -19
  57. package/src/packlets/identity/identity-service.test.ts +4 -8
  58. package/src/packlets/identity/identity.test.ts +128 -239
  59. package/src/packlets/identity/identity.ts +38 -8
  60. package/src/packlets/invitations/device-invitation-protocol.test.ts +7 -4
  61. package/src/packlets/invitations/invitation-host-extension.ts +0 -3
  62. package/src/packlets/invitations/invitations-handler.test.ts +14 -7
  63. package/src/packlets/invitations/invitations-handler.ts +1 -1
  64. package/src/packlets/invitations/space-invitation-protocol.test.ts +4 -3
  65. package/src/packlets/logging/logging.test.ts +1 -2
  66. package/src/packlets/network/network-service.test.ts +2 -3
  67. package/src/packlets/services/service-context.test.ts +3 -1
  68. package/src/packlets/services/service-context.ts +24 -12
  69. package/src/packlets/services/service-host.test.ts +8 -12
  70. package/src/packlets/services/service-host.ts +2 -2
  71. package/src/packlets/services/service-registry.test.ts +1 -2
  72. package/src/packlets/spaces/data-space-manager.test.ts +2 -2
  73. package/src/packlets/spaces/data-space-manager.ts +4 -1
  74. package/src/packlets/spaces/data-space.ts +7 -2
  75. package/src/packlets/spaces/edge-feed-replicator.test.ts +244 -0
  76. package/src/packlets/spaces/edge-feed-replicator.ts +59 -21
  77. package/src/packlets/spaces/epoch-migrations.ts +2 -2
  78. package/src/packlets/spaces/notarization-plugin.test.ts +2 -3
  79. package/src/packlets/spaces/spaces-service.test.ts +5 -9
  80. package/src/packlets/storage/storage.ts +0 -1
  81. package/src/packlets/system/system-service.test.ts +1 -2
  82. package/src/packlets/testing/test-builder.ts +1 -2
  83. package/src/packlets/worker/worker-runtime.ts +2 -2
  84. package/src/testing/setup.ts +11 -0
  85. package/src/version.ts +1 -5
  86. package/dist/lib/browser/chunk-QYVLLBAA.mjs.map +0 -7
  87. package/dist/lib/node/chunk-F7G2TXVG.cjs.map +0 -7
  88. package/dist/types/src/packlets/identity/authenticator.test.d.ts +0 -2
  89. package/dist/types/src/packlets/identity/authenticator.test.d.ts.map +0 -1
  90. package/dist/types/src/packlets/services/automerge-host.test.d.ts +0 -2
  91. package/dist/types/src/packlets/services/automerge-host.test.d.ts.map +0 -1
  92. package/src/packlets/services/automerge-host.test.ts +0 -60
@@ -5,15 +5,19 @@
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 { Resource, type Context } from '@dxos/context';
8
+ import { Context, Resource } from '@dxos/context';
9
9
  import { type EdgeConnection } from '@dxos/edge-client';
10
+ import { EdgeConnectionClosedError, EdgeIdentityChangedError } from '@dxos/edge-client';
10
11
  import { type FeedWrapper } from '@dxos/feed-store';
11
12
  import { invariant } from '@dxos/invariant';
12
13
  import { PublicKey, type SpaceId } from '@dxos/keys';
13
14
  import { log } from '@dxos/log';
14
15
  import { EdgeService } from '@dxos/protocols';
15
16
  import { buf } from '@dxos/protocols/buf';
16
- import { MessageSchema as RouterMessageSchema } from '@dxos/protocols/buf/dxos/edge/messenger_pb';
17
+ import {
18
+ MessageSchema as RouterMessageSchema,
19
+ type Message as RouterMessage,
20
+ } from '@dxos/protocols/buf/dxos/edge/messenger_pb';
17
21
  import type { FeedBlock, ProtocolMessage } from '@dxos/protocols/feed-replication';
18
22
  import { ComplexMap, arrayToBuffer, bufferToArray, defaultMap, rangeFromTo } from '@dxos/util';
19
23
 
@@ -48,7 +52,7 @@ export class EdgeFeedReplicator extends Resource {
48
52
  protected override async _open(): Promise<void> {
49
53
  // TODO: handle reconnects
50
54
  this._ctx.onDispose(
51
- this._messenger.addListener(async (message) => {
55
+ this._messenger.addListener((message: RouterMessage) => {
52
56
  if (!message.serviceId) {
53
57
  return;
54
58
  }
@@ -64,21 +68,43 @@ export class EdgeFeedReplicator extends Resource {
64
68
  }
65
69
 
66
70
  const payload = decodeCbor(message.payload!.value) as ProtocolMessage;
67
- log.info('recv', { from: message.source, payload });
71
+ log.info('receive', { from: message.source, feedKey: payload.feedKey, type: payload.type });
68
72
  this._onMessage(payload);
69
73
  }),
70
74
  );
71
75
 
72
- this._connected = true;
73
- this._connectionCtx = this._ctx.derive();
74
- for (const feed of this._feeds.values()) {
75
- await this._replicateFeed(feed);
76
- }
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
+ });
77
101
  }
78
102
 
79
103
  protected override async _close(): Promise<void> {
80
- this._connected = false;
104
+ await this._resetConnection();
105
+ }
81
106
 
107
+ private async _resetConnection() {
82
108
  this._connected = false;
83
109
  await this._connectionCtx?.dispose();
84
110
  this._connectionCtx = undefined;
@@ -89,8 +115,8 @@ export class EdgeFeedReplicator extends Resource {
89
115
  log.info('addFeed', { key: feed.key });
90
116
  this._feeds.set(feed.key, feed);
91
117
 
92
- if (this._connected) {
93
- await this._replicateFeed(feed);
118
+ if (this._connected && this._connectionCtx) {
119
+ await this._replicateFeed(this._connectionCtx, feed);
94
120
  }
95
121
  }
96
122
 
@@ -98,21 +124,26 @@ export class EdgeFeedReplicator extends Resource {
98
124
  return defaultMap(this._pushMutex, key, () => new Mutex());
99
125
  }
100
126
 
101
- private async _replicateFeed(feed: FeedWrapper<any>) {
102
- invariant(this._connectionCtx);
103
-
127
+ private async _replicateFeed(ctx: Context, feed: FeedWrapper<any>) {
104
128
  await this._sendMessage({
105
129
  type: 'get-metadata',
106
130
  feedKey: feed.key.toHex(),
107
131
  });
108
132
 
109
- Event.wrap(feed.core as any, 'append').on(this._connectionCtx, async () => {
133
+ Event.wrap(feed.core as any, 'append').on(ctx, async () => {
110
134
  await this._pushBlocksIfNeeded(feed);
111
135
  });
112
136
  }
113
137
 
114
138
  private async _sendMessage(message: ProtocolMessage) {
115
- log.info('sending message', { message });
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);
116
147
 
117
148
  invariant(message.feedKey);
118
149
  const payloadValue = bufferToArray(encodeCbor(message));
@@ -130,11 +161,15 @@ export class EdgeFeedReplicator extends Resource {
130
161
  }
131
162
 
132
163
  private _onMessage(message: ProtocolMessage) {
133
- log.info('received message', { message });
134
-
135
- scheduleMicroTask(this._ctx, async () => {
164
+ if (!this._connectionCtx) {
165
+ log.warn('received message after connection context was disposed');
166
+ return;
167
+ }
168
+ scheduleMicroTask(this._connectionCtx, async () => {
136
169
  switch (message.type) {
137
170
  case 'metadata': {
171
+ log.info('received metadata', { message });
172
+
138
173
  const feedKey = PublicKey.fromHex(message.feedKey);
139
174
  const feed = this._feeds.get(feedKey);
140
175
  if (!feed) {
@@ -160,6 +195,8 @@ export class EdgeFeedReplicator extends Resource {
160
195
  }
161
196
 
162
197
  case 'data': {
198
+ log.info('received data', { feed: message.feedKey, blocks: message.blocks.map((b) => b.index) });
199
+
163
200
  const feedKey = PublicKey.fromHex(message.feedKey);
164
201
  const feed = this._feeds.get(feedKey);
165
202
  if (!feed) {
@@ -223,9 +260,10 @@ export class EdgeFeedReplicator extends Resource {
223
260
  }
224
261
 
225
262
  private async _pushBlocksIfNeeded(feed: FeedWrapper<any>) {
226
- using _guard = await this._getPushMutex(feed.key).acquire();
263
+ using _ = await this._getPushMutex(feed.key).acquire();
227
264
 
228
265
  if (!this._remoteLength.has(feed.key)) {
266
+ log('blocks not pushed because remote length is unknown');
229
267
  return;
230
268
  }
231
269
 
@@ -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';
7
8
  import {
8
9
  convertLegacyReferences,
9
10
  convertLegacySpaceRootDoc,
10
11
  findInlineObjectOfType,
11
- migrateDocument,
12
12
  type EchoHost,
13
- } from '@dxos/echo-db';
13
+ } from '@dxos/echo-pipeline';
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 { expect } from 'chai';
5
+ import { onTestFinished, describe, expect, test } from 'vitest';
6
6
 
7
7
  import { Context } from '@dxos/context';
8
8
  import { CredentialGenerator } from '@dxos/credentials';
@@ -11,7 +11,6 @@ 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';
15
14
 
16
15
  import { NotarizationPlugin } from './notarization-plugin';
17
16
 
@@ -49,7 +48,7 @@ class TestAgent extends TestPeer {
49
48
  describe('NotarizationPlugin', () => {
50
49
  test('notarize single credential', async () => {
51
50
  const testBuilder = new TestBuilder();
52
- afterTest(() => testBuilder.destroy());
51
+ onTestFinished(() => testBuilder.destroy());
53
52
 
54
53
  // peer0 is there to test retries.
55
54
  const [_peer0, peer1, peer2] = await testBuilder.createPeers({ factory: () => new TestAgent() });
@@ -2,21 +2,17 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import chai, { expect } from 'chai';
6
- import chaiAsPromised from 'chai-as-promised';
5
+ import { afterEach, onTestFinished, beforeEach, describe, expect, test } from 'vitest';
7
6
 
8
7
  import { Trigger } from '@dxos/async';
9
8
  import { Context } from '@dxos/context';
10
9
  import { PublicKey } from '@dxos/keys';
11
10
  import { type Space, type SpacesService } from '@dxos/protocols/proto/dxos/client/services';
12
- import { afterEach, afterTest, beforeEach, describe, test } from '@dxos/test';
13
11
 
14
12
  import { SpacesServiceImpl } from './spaces-service';
15
13
  import { type ServiceContext } from '../services';
16
14
  import { createServiceContext } from '../testing';
17
15
 
18
- chai.use(chaiAsPromised);
19
-
20
16
  describe('SpacesService', () => {
21
17
  let serviceContext: ServiceContext;
22
18
  let spacesService: SpacesService;
@@ -36,7 +32,7 @@ describe('SpacesService', () => {
36
32
 
37
33
  describe('createSpace', () => {
38
34
  test('fails if no identity is available', async () => {
39
- await expect(spacesService.createSpace()).to.be.rejectedWith();
35
+ await expect(spacesService.createSpace()).rejects.toBeInstanceOf(Error);
40
36
  });
41
37
 
42
38
  test('creates a new space', async () => {
@@ -56,7 +52,7 @@ describe('SpacesService', () => {
56
52
  query.subscribe(({ spaces }) => {
57
53
  result.wake(spaces);
58
54
  });
59
- afterTest(() => query.close());
55
+ onTestFinished(() => query.close());
60
56
  expect(await result.wait()).to.be.length(0);
61
57
  });
62
58
 
@@ -73,7 +69,7 @@ describe('SpacesService', () => {
73
69
  query.subscribe(({ spaces }) => {
74
70
  result.wake(spaces);
75
71
  });
76
- afterTest(() => query.close());
72
+ onTestFinished(() => query.close());
77
73
 
78
74
  const spaces = await result.wait();
79
75
  expect(spaces).to.be.length(3);
@@ -87,7 +83,7 @@ describe('SpacesService', () => {
87
83
  query.subscribe(({ spaces }) => {
88
84
  result.wake(spaces);
89
85
  });
90
- afterTest(() => query.close());
86
+ onTestFinished(() => query.close());
91
87
  expect(await result.wait()).to.be.length(0);
92
88
 
93
89
  result.reset();
@@ -14,7 +14,6 @@ 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
-
18
17
  if (persistent && dataStore === StorageDriver.RAM) {
19
18
  throw new InvalidConfigError('RAM storage cannot be used in persistent mode.');
20
19
  }
@@ -2,12 +2,11 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { expect } from 'chai';
5
+ import { beforeEach, describe, expect, test } from 'vitest';
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';
11
10
 
12
11
  import { SystemServiceImpl } from './system-service';
13
12
 
@@ -6,8 +6,7 @@ import { type Config } from '@dxos/config';
6
6
  import { Context } from '@dxos/context';
7
7
  import { createCredentialSignerWithChain, CredentialGenerator } from '@dxos/credentials';
8
8
  import { failUndefined } from '@dxos/debug';
9
- import { EchoHost } from '@dxos/echo-db';
10
- import { MetadataStore, SpaceManager, valueEncoding, MeshEchoReplicator } from '@dxos/echo-pipeline';
9
+ import { EchoHost, MetadataStore, SpaceManager, valueEncoding, MeshEchoReplicator } from '@dxos/echo-pipeline';
11
10
  import { FeedFactory, FeedStore } from '@dxos/feed-store';
12
11
  import { Keyring } from '@dxos/keyring';
13
12
  import { type LevelDB } from '@dxos/kv-store';
@@ -14,7 +14,7 @@ import {
14
14
  WebsocketSignalManager,
15
15
  setIdentityTags,
16
16
  } from '@dxos/messaging';
17
- import { SimplePeerTransportProxyFactory } from '@dxos/network-manager';
17
+ import { RtcTransportProxyFactory } from '@dxos/network-manager';
18
18
  import { type RpcPort } from '@dxos/rpc';
19
19
  import { type MaybePromise } from '@dxos/util';
20
20
 
@@ -46,7 +46,7 @@ export class WorkerRuntime {
46
46
  private readonly _acquireLock: () => Promise<void>;
47
47
  private readonly _releaseLock: () => void;
48
48
  private readonly _onStop?: () => Promise<void>;
49
- private readonly _transportFactory = new SimplePeerTransportProxyFactory();
49
+ private readonly _transportFactory = new RtcTransportProxyFactory();
50
50
  private readonly _ready = new Trigger<Error | undefined>();
51
51
  private readonly _sessions = new Set<WorkerSession>();
52
52
  private readonly _clientServices!: ClientServicesHost;
@@ -0,0 +1,11 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { runTestSignalServer } from '@dxos/signal';
6
+
7
+ const port = 12004;
8
+
9
+ export default async () => {
10
+ await runTestSignalServer({ port, killExisting: true });
11
+ };
package/src/version.ts CHANGED
@@ -1,5 +1 @@
1
- //
2
- // Copyright 2023 DXOS.org
3
- //
4
-
5
- export const DXOS_VERSION = '0.6.11'; // {x-release-please-version}
1
+ export const DXOS_VERSION = "0.6.12-main.5a87ad5";