@dxos/client-services 0.6.13 → 0.6.14-main.69511f5
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.
- package/dist/lib/browser/{chunk-CRXXOI45.mjs → chunk-PK5RMXEO.mjs} +6462 -5230
- package/dist/lib/browser/chunk-PK5RMXEO.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +7 -3
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +12 -8
- package/dist/lib/browser/testing/index.mjs.map +3 -3
- package/dist/lib/node/{chunk-PZ3JJJ3K.cjs → chunk-XDE6WELX.cjs} +6287 -5057
- package/dist/lib/node/chunk-XDE6WELX.cjs.map +7 -0
- package/dist/lib/node/index.cjs +50 -46
- package/dist/lib/node/index.cjs.map +3 -3
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/testing/index.cjs +18 -13
- package/dist/lib/node/testing/index.cjs.map +3 -3
- package/dist/lib/node-esm/chunk-S5DTGWTU.mjs +8956 -0
- package/dist/lib/node-esm/chunk-S5DTGWTU.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +420 -0
- package/dist/lib/node-esm/index.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -0
- package/dist/lib/node-esm/testing/index.mjs +424 -0
- package/dist/lib/node-esm/testing/index.mjs.map +7 -0
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/packlets/agents/edge-agent-manager.d.ts +35 -0
- package/dist/types/src/packlets/agents/edge-agent-manager.d.ts.map +1 -0
- package/dist/types/src/packlets/agents/edge-agent-service.d.ts +10 -0
- package/dist/types/src/packlets/agents/edge-agent-service.d.ts.map +1 -0
- package/dist/types/src/packlets/agents/index.d.ts +3 -0
- package/dist/types/src/packlets/agents/index.d.ts.map +1 -0
- package/dist/types/src/packlets/diagnostics/diagnostics-broadcast.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/authenticator.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/authenticator.node.test.d.ts +2 -0
- package/dist/types/src/packlets/identity/authenticator.node.test.d.ts.map +1 -0
- package/dist/types/src/packlets/identity/contacts-service.d.ts +1 -1
- package/dist/types/src/packlets/identity/contacts-service.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity-manager.d.ts +28 -9
- package/dist/types/src/packlets/identity/identity-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts +18 -0
- package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts.map +1 -0
- package/dist/types/src/packlets/identity/identity-service.d.ts +7 -2
- package/dist/types/src/packlets/identity/identity-service.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity.d.ts +12 -3
- package/dist/types/src/packlets/identity/identity.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/edge-invitation-handler.d.ts +30 -0
- package/dist/types/src/packlets/invitations/edge-invitation-handler.d.ts.map +1 -0
- package/dist/types/src/packlets/invitations/invitation-guest-extenstion.d.ts +2 -1
- package/dist/types/src/packlets/invitations/invitation-guest-extenstion.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitation-host-extension.d.ts +2 -1
- package/dist/types/src/packlets/invitations/invitation-host-extension.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitation-state.d.ts +19 -0
- package/dist/types/src/packlets/invitations/invitation-state.d.ts.map +1 -0
- package/dist/types/src/packlets/invitations/invitations-handler.d.ts +8 -8
- package/dist/types/src/packlets/invitations/invitations-handler.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts.map +1 -1
- package/dist/types/src/packlets/services/service-context.d.ts +14 -9
- package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
- package/dist/types/src/packlets/services/service-host.d.ts +2 -0
- package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/data-space-manager.d.ts +7 -3
- package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/data-space.d.ts +5 -3
- package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts +3 -0
- package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/edge-feed-replicator.test.d.ts +2 -0
- package/dist/types/src/packlets/spaces/edge-feed-replicator.test.d.ts.map +1 -0
- package/dist/types/src/packlets/spaces/epoch-migrations.d.ts +1 -1
- package/dist/types/src/packlets/spaces/epoch-migrations.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/notarization-plugin.d.ts +35 -6
- package/dist/types/src/packlets/spaces/notarization-plugin.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/spaces-service.d.ts +1 -1
- package/dist/types/src/packlets/spaces/spaces-service.d.ts.map +1 -1
- package/dist/types/src/packlets/storage/storage.d.ts.map +1 -1
- package/dist/types/src/packlets/testing/test-builder.d.ts +1 -2
- package/dist/types/src/packlets/testing/test-builder.d.ts.map +1 -1
- package/dist/types/src/packlets/worker/worker-runtime.d.ts.map +1 -1
- package/dist/types/src/testing/setup.d.ts +3 -0
- package/dist/types/src/testing/setup.d.ts.map +1 -0
- package/dist/types/src/version.d.ts +1 -1
- package/dist/types/src/version.d.ts.map +1 -1
- package/package.json +44 -45
- package/src/index.ts +1 -0
- package/src/packlets/agents/edge-agent-manager.ts +163 -0
- package/src/packlets/agents/edge-agent-service.ts +42 -0
- package/src/packlets/agents/index.ts +6 -0
- package/src/packlets/devices/devices-service.test.ts +4 -5
- package/src/packlets/diagnostics/diagnostics-broadcast.ts +1 -0
- package/src/packlets/identity/{authenticator.test.ts → authenticator.node.test.ts} +2 -3
- package/src/packlets/identity/authenticator.ts +5 -2
- package/src/packlets/identity/contacts-service.ts +1 -1
- package/src/packlets/identity/identity-manager.test.ts +31 -16
- package/src/packlets/identity/identity-manager.ts +76 -32
- package/src/packlets/identity/identity-recovery-manager.ts +95 -0
- package/src/packlets/identity/identity-service.test.ts +5 -8
- package/src/packlets/identity/identity-service.ts +11 -5
- package/src/packlets/identity/identity.test.ts +130 -239
- package/src/packlets/identity/identity.ts +60 -17
- package/src/packlets/invitations/device-invitation-protocol.test.ts +7 -4
- package/src/packlets/invitations/device-invitation-protocol.ts +8 -2
- package/src/packlets/invitations/edge-invitation-handler.ts +185 -0
- package/src/packlets/invitations/invitation-guest-extenstion.ts +8 -4
- package/src/packlets/invitations/invitation-host-extension.ts +8 -7
- package/src/packlets/invitations/invitation-state.ts +112 -0
- package/src/packlets/invitations/invitations-handler.test.ts +16 -9
- package/src/packlets/invitations/invitations-handler.ts +57 -98
- package/src/packlets/invitations/space-invitation-protocol.test.ts +4 -3
- package/src/packlets/invitations/space-invitation-protocol.ts +5 -0
- package/src/packlets/logging/logging.test.ts +1 -2
- package/src/packlets/network/network-service.test.ts +2 -3
- package/src/packlets/services/service-context.test.ts +3 -1
- package/src/packlets/services/service-context.ts +113 -35
- package/src/packlets/services/service-host.test.ts +8 -12
- package/src/packlets/services/service-host.ts +25 -7
- package/src/packlets/services/service-registry.test.ts +1 -2
- package/src/packlets/spaces/data-space-manager.test.ts +2 -2
- package/src/packlets/spaces/data-space-manager.ts +44 -7
- package/src/packlets/spaces/data-space.ts +37 -6
- package/src/packlets/spaces/edge-feed-replicator.test.ts +252 -0
- package/src/packlets/spaces/edge-feed-replicator.ts +80 -22
- package/src/packlets/spaces/epoch-migrations.ts +2 -2
- package/src/packlets/spaces/notarization-plugin.test.ts +10 -7
- package/src/packlets/spaces/notarization-plugin.ts +196 -29
- package/src/packlets/spaces/spaces-service.test.ts +5 -9
- package/src/packlets/spaces/spaces-service.ts +6 -1
- package/src/packlets/storage/storage.ts +0 -1
- package/src/packlets/system/system-service.test.ts +1 -2
- package/src/packlets/testing/test-builder.ts +7 -4
- package/src/packlets/worker/worker-runtime.ts +2 -2
- package/src/testing/setup.ts +11 -0
- package/src/version.ts +1 -5
- package/dist/lib/browser/chunk-CRXXOI45.mjs.map +0 -7
- package/dist/lib/node/chunk-PZ3JJJ3K.cjs.map +0 -7
- package/dist/types/src/packlets/identity/authenticator.test.d.ts +0 -2
- package/dist/types/src/packlets/identity/authenticator.test.d.ts.map +0 -1
- package/dist/types/src/packlets/services/automerge-host.test.d.ts +0 -2
- package/dist/types/src/packlets/services/automerge-host.test.d.ts.map +0 -1
- package/src/packlets/services/automerge-host.test.ts +0 -60
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import chai, { expect } from 'chai';
|
|
6
|
-
import chaiAsPromised from 'chai-as-promised';
|
|
7
5
|
import { rmSync } from 'node:fs';
|
|
6
|
+
import { afterEach, onTestFinished, describe, expect, test } from 'vitest';
|
|
8
7
|
|
|
9
8
|
import { asyncTimeout, latch, Trigger } from '@dxos/async';
|
|
10
9
|
import { Config } from '@dxos/config';
|
|
@@ -14,13 +13,10 @@ import { type PublicKey } from '@dxos/keys';
|
|
|
14
13
|
import { MemorySignalManagerContext } from '@dxos/messaging';
|
|
15
14
|
import { type Identity } from '@dxos/protocols/proto/dxos/client/services';
|
|
16
15
|
import { type Credential } from '@dxos/protocols/proto/dxos/halo/credentials';
|
|
17
|
-
import { afterTest, describe, test } from '@dxos/test';
|
|
18
16
|
import { isNode } from '@dxos/util';
|
|
19
17
|
|
|
20
18
|
import { createMockCredential, createServiceHost } from '../testing';
|
|
21
19
|
|
|
22
|
-
chai.use(chaiAsPromised);
|
|
23
|
-
|
|
24
20
|
describe('ClientServicesHost', () => {
|
|
25
21
|
const dataRoot = '/tmp/dxos/client-services/service-host/storage';
|
|
26
22
|
|
|
@@ -38,7 +34,7 @@ describe('ClientServicesHost', () => {
|
|
|
38
34
|
test('queryCredentials', async () => {
|
|
39
35
|
const host = createServiceHost(new Config(), new MemorySignalManagerContext());
|
|
40
36
|
await host.open(new Context());
|
|
41
|
-
|
|
37
|
+
onTestFinished(() => host.close());
|
|
42
38
|
|
|
43
39
|
await host.services.IdentityService!.createIdentity({});
|
|
44
40
|
const { spaceKey } = await host.services.SpacesService!.createSpace();
|
|
@@ -49,7 +45,7 @@ describe('ClientServicesHost', () => {
|
|
|
49
45
|
tick();
|
|
50
46
|
// console.log(credential);
|
|
51
47
|
});
|
|
52
|
-
|
|
48
|
+
onTestFinished(() => stream.close());
|
|
53
49
|
|
|
54
50
|
await done();
|
|
55
51
|
});
|
|
@@ -57,7 +53,7 @@ describe('ClientServicesHost', () => {
|
|
|
57
53
|
test('write and query credentials', async () => {
|
|
58
54
|
const host = createServiceHost(new Config(), new MemorySignalManagerContext());
|
|
59
55
|
await host.open(new Context());
|
|
60
|
-
|
|
56
|
+
onTestFinished(() => host.close());
|
|
61
57
|
|
|
62
58
|
await host.services.IdentityService!.createIdentity({});
|
|
63
59
|
|
|
@@ -86,7 +82,7 @@ describe('ClientServicesHost', () => {
|
|
|
86
82
|
queriedCredential.wake(credential);
|
|
87
83
|
}
|
|
88
84
|
});
|
|
89
|
-
|
|
85
|
+
onTestFinished(() => credentials.close());
|
|
90
86
|
|
|
91
87
|
await queriedCredential.wait();
|
|
92
88
|
});
|
|
@@ -94,7 +90,7 @@ describe('ClientServicesHost', () => {
|
|
|
94
90
|
test('sign presentation', async () => {
|
|
95
91
|
const host = createServiceHost(new Config(), new MemorySignalManagerContext());
|
|
96
92
|
await host.open(new Context());
|
|
97
|
-
|
|
93
|
+
onTestFinished(() => host.close());
|
|
98
94
|
|
|
99
95
|
await host.services.IdentityService!.createIdentity({});
|
|
100
96
|
|
|
@@ -147,9 +143,9 @@ describe('ClientServicesHost', () => {
|
|
|
147
143
|
trigger.wake(identity.identity);
|
|
148
144
|
}
|
|
149
145
|
});
|
|
150
|
-
await expect(asyncTimeout(trigger.wait(), 200)).
|
|
146
|
+
await expect(asyncTimeout(trigger.wait(), 200)).rejects.toBeInstanceOf(Error);
|
|
151
147
|
await stream?.close();
|
|
152
148
|
await host.close();
|
|
153
149
|
}
|
|
154
|
-
})
|
|
150
|
+
});
|
|
155
151
|
});
|
|
@@ -6,7 +6,7 @@ import { Event, synchronized } from '@dxos/async';
|
|
|
6
6
|
import { clientServiceBundle, type ClientServices } from '@dxos/client-protocol';
|
|
7
7
|
import { type Config } from '@dxos/config';
|
|
8
8
|
import { Context } from '@dxos/context';
|
|
9
|
-
import { EdgeClient, type EdgeConnection } from '@dxos/edge-client';
|
|
9
|
+
import { EdgeClient, EdgeHttpClient, createStubEdgeIdentity, type EdgeConnection } from '@dxos/edge-client';
|
|
10
10
|
import { invariant } from '@dxos/invariant';
|
|
11
11
|
import { PublicKey } from '@dxos/keys';
|
|
12
12
|
import { type LevelDB } from '@dxos/kv-store';
|
|
@@ -15,7 +15,7 @@ import { EdgeSignalManager, WebsocketSignalManager, type SignalManager } from '@
|
|
|
15
15
|
import {
|
|
16
16
|
SwarmNetworkManager,
|
|
17
17
|
createIceProvider,
|
|
18
|
-
|
|
18
|
+
createRtcTransportFactory,
|
|
19
19
|
type TransportFactory,
|
|
20
20
|
} from '@dxos/network-manager';
|
|
21
21
|
import { trace } from '@dxos/protocols';
|
|
@@ -26,12 +26,13 @@ import { WebsocketRpcClient } from '@dxos/websocket-rpc';
|
|
|
26
26
|
|
|
27
27
|
import { ServiceContext, type ServiceContextRuntimeParams } from './service-context';
|
|
28
28
|
import { ServiceRegistry } from './service-registry';
|
|
29
|
+
import { EdgeAgentServiceImpl } from '../agents';
|
|
29
30
|
import { DevicesServiceImpl } from '../devices';
|
|
30
31
|
import { DevtoolsHostEvents, DevtoolsServiceImpl } from '../devtools';
|
|
31
32
|
import {
|
|
32
|
-
type CollectDiagnosticsBroadcastHandler,
|
|
33
33
|
createCollectDiagnosticsBroadcastHandler,
|
|
34
34
|
createDiagnostics,
|
|
35
|
+
type CollectDiagnosticsBroadcastHandler,
|
|
35
36
|
} from '../diagnostics';
|
|
36
37
|
import { IdentityServiceImpl, type CreateIdentityOptions } from '../identity';
|
|
37
38
|
import { ContactsServiceImpl } from '../identity/contacts-service';
|
|
@@ -89,6 +90,7 @@ export class ClientServicesHost {
|
|
|
89
90
|
private _callbacks?: ClientServicesHostCallbacks;
|
|
90
91
|
private _devtoolsProxy?: WebsocketRpcClient<{}, ClientServices>;
|
|
91
92
|
private _edgeConnection?: EdgeConnection = undefined;
|
|
93
|
+
private _edgeHttpClient?: EdgeHttpClient = undefined;
|
|
92
94
|
|
|
93
95
|
private _serviceContext!: ServiceContext;
|
|
94
96
|
private readonly _runtimeParams: ServiceContextRuntimeParams;
|
|
@@ -100,6 +102,9 @@ export class ClientServicesHost {
|
|
|
100
102
|
@Trace.info()
|
|
101
103
|
private _open = false;
|
|
102
104
|
|
|
105
|
+
@Trace.info()
|
|
106
|
+
private _resetting = false;
|
|
107
|
+
|
|
103
108
|
constructor({
|
|
104
109
|
config,
|
|
105
110
|
transportFactory,
|
|
@@ -140,7 +145,7 @@ export class ClientServicesHost {
|
|
|
140
145
|
this._systemService = new SystemServiceImpl({
|
|
141
146
|
config: () => this._config,
|
|
142
147
|
statusUpdate: this._statusUpdate,
|
|
143
|
-
getCurrentStatus: () => (this.isOpen ? SystemStatus.ACTIVE : SystemStatus.INACTIVE),
|
|
148
|
+
getCurrentStatus: () => (this.isOpen && !this._resetting ? SystemStatus.ACTIVE : SystemStatus.INACTIVE),
|
|
144
149
|
getDiagnostics: () => {
|
|
145
150
|
return createDiagnostics(this._serviceRegistry.services, this._serviceContext, this._config!);
|
|
146
151
|
},
|
|
@@ -212,13 +217,13 @@ export class ClientServicesHost {
|
|
|
212
217
|
|
|
213
218
|
const edgeEndpoint = config?.get('runtime.services.edge.url');
|
|
214
219
|
if (edgeEndpoint) {
|
|
215
|
-
|
|
216
|
-
this.
|
|
220
|
+
this._edgeConnection = new EdgeClient(createStubEdgeIdentity(), { socketEndpoint: edgeEndpoint });
|
|
221
|
+
this._edgeHttpClient = new EdgeHttpClient(edgeEndpoint);
|
|
217
222
|
}
|
|
218
223
|
|
|
219
224
|
const {
|
|
220
225
|
connectionLog = true,
|
|
221
|
-
transportFactory =
|
|
226
|
+
transportFactory = createRtcTransportFactory(
|
|
222
227
|
{ iceServers: this._config?.get('runtime.services.ice') },
|
|
223
228
|
this._config?.get('runtime.services.iceProviders') &&
|
|
224
229
|
createIceProvider(this._config!.get('runtime.services.iceProviders')!),
|
|
@@ -278,6 +283,7 @@ export class ClientServicesHost {
|
|
|
278
283
|
this._networkManager,
|
|
279
284
|
this._signalManager,
|
|
280
285
|
this._edgeConnection,
|
|
286
|
+
this._edgeHttpClient,
|
|
281
287
|
this._runtimeParams,
|
|
282
288
|
this._config.get('runtime.client.edgeFeatures'),
|
|
283
289
|
);
|
|
@@ -287,8 +293,14 @@ export class ClientServicesHost {
|
|
|
287
293
|
return this._serviceContext.dataSpaceManager!;
|
|
288
294
|
};
|
|
289
295
|
|
|
296
|
+
const agentManagerProvider = async () => {
|
|
297
|
+
await this._serviceContext.initialized.wait();
|
|
298
|
+
return this._serviceContext.edgeAgentManager!;
|
|
299
|
+
};
|
|
300
|
+
|
|
290
301
|
const identityService = new IdentityServiceImpl(
|
|
291
302
|
this._serviceContext.identityManager,
|
|
303
|
+
this._serviceContext.recoveryManager,
|
|
292
304
|
this._serviceContext.keyring,
|
|
293
305
|
() => this._serviceContext.dataSpaceManager!,
|
|
294
306
|
(params) => this._createIdentity(params),
|
|
@@ -328,6 +340,8 @@ export class ClientServicesHost {
|
|
|
328
340
|
config: this._config,
|
|
329
341
|
context: this._serviceContext,
|
|
330
342
|
}),
|
|
343
|
+
|
|
344
|
+
EdgeAgentService: new EdgeAgentServiceImpl(agentManagerProvider),
|
|
331
345
|
});
|
|
332
346
|
|
|
333
347
|
await this._serviceContext.open(ctx);
|
|
@@ -378,6 +392,10 @@ export class ClientServicesHost {
|
|
|
378
392
|
log.trace('dxos.sdk.client-services-host.reset', trace.begin({ id: traceId }));
|
|
379
393
|
|
|
380
394
|
log.info('resetting...');
|
|
395
|
+
// Emit this status update immediately so app returns to fallback.
|
|
396
|
+
// This state is never cleared because the app reloads.
|
|
397
|
+
this._resetting = true;
|
|
398
|
+
this._statusUpdate.emit();
|
|
381
399
|
await this._serviceContext?.close();
|
|
382
400
|
await this._storage!.reset();
|
|
383
401
|
log.info('reset');
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Copyright 2022 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { expect } from '
|
|
5
|
+
import { describe, expect, test } from 'vitest';
|
|
6
6
|
|
|
7
7
|
import { Event } from '@dxos/async';
|
|
8
8
|
import { type ClientServices } from '@dxos/client-protocol';
|
|
@@ -12,7 +12,6 @@ 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';
|
|
16
15
|
|
|
17
16
|
import { ServiceRegistry } from './service-registry';
|
|
18
17
|
import { SystemServiceImpl } from '../system';
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Copyright 2022 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { expect } from '
|
|
5
|
+
import { describe, expect, test } from 'vitest';
|
|
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 {
|
|
13
|
+
import { openAndClose } from '@dxos/test-utils';
|
|
14
14
|
|
|
15
15
|
import { TestBuilder, type TestPeer } from '../testing';
|
|
16
16
|
|
|
@@ -14,8 +14,11 @@ 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';
|
|
18
17
|
import {
|
|
18
|
+
convertLegacyReferences,
|
|
19
|
+
findInlineObjectOfType,
|
|
20
|
+
type EchoEdgeReplicator,
|
|
21
|
+
type EchoHost,
|
|
19
22
|
AuthStatus,
|
|
20
23
|
CredentialServerExtension,
|
|
21
24
|
type MeshEchoReplicator,
|
|
@@ -32,8 +35,8 @@ import {
|
|
|
32
35
|
type ObjectStructure,
|
|
33
36
|
type SpaceDoc,
|
|
34
37
|
} from '@dxos/echo-protocol';
|
|
35
|
-
import { TYPE_PROPERTIES,
|
|
36
|
-
import type { EdgeConnection } from '@dxos/edge-client';
|
|
38
|
+
import { TYPE_PROPERTIES, createObjectId, getTypeReference } from '@dxos/echo-schema';
|
|
39
|
+
import type { EdgeConnection, EdgeHttpClient } from '@dxos/edge-client';
|
|
37
40
|
import { writeMessages, type FeedStore } from '@dxos/feed-store';
|
|
38
41
|
import { invariant } from '@dxos/invariant';
|
|
39
42
|
import { type Keyring } from '@dxos/keyring';
|
|
@@ -43,7 +46,7 @@ import { AlreadyJoinedError, trace as Trace } from '@dxos/protocols';
|
|
|
43
46
|
import { Invitation, SpaceState } from '@dxos/protocols/proto/dxos/client/services';
|
|
44
47
|
import { type Runtime } from '@dxos/protocols/proto/dxos/config';
|
|
45
48
|
import { type FeedMessage } from '@dxos/protocols/proto/dxos/echo/feed';
|
|
46
|
-
import { type SpaceMetadata } from '@dxos/protocols/proto/dxos/echo/metadata';
|
|
49
|
+
import { type SpaceMetadata, EdgeReplicationSetting } from '@dxos/protocols/proto/dxos/echo/metadata';
|
|
47
50
|
import { SpaceMember, type Credential, type ProfileDocument } from '@dxos/protocols/proto/dxos/halo/credentials';
|
|
48
51
|
import { type DelegateSpaceInvitation } from '@dxos/protocols/proto/dxos/halo/invitations';
|
|
49
52
|
import { type PeerState } from '@dxos/protocols/proto/dxos/mesh/presence';
|
|
@@ -107,6 +110,7 @@ export type DataSpaceManagerParams = {
|
|
|
107
110
|
echoHost: EchoHost;
|
|
108
111
|
invitationsManager: InvitationsManager;
|
|
109
112
|
edgeConnection?: EdgeConnection;
|
|
113
|
+
edgeHttpClient?: EdgeHttpClient;
|
|
110
114
|
meshReplicator?: MeshEchoReplicator;
|
|
111
115
|
echoEdgeReplicator?: EchoEdgeReplicator;
|
|
112
116
|
runtimeParams?: DataSpaceManagerRuntimeParams;
|
|
@@ -116,6 +120,7 @@ export type DataSpaceManagerParams = {
|
|
|
116
120
|
export type DataSpaceManagerRuntimeParams = {
|
|
117
121
|
spaceMemberPresenceAnnounceInterval?: number;
|
|
118
122
|
spaceMemberPresenceOfflineTimeout?: number;
|
|
123
|
+
activeEdgeNotarizationPollingInterval?: number;
|
|
119
124
|
disableP2pReplication?: boolean;
|
|
120
125
|
};
|
|
121
126
|
|
|
@@ -135,6 +140,7 @@ export class DataSpaceManager extends Resource {
|
|
|
135
140
|
private readonly _echoHost: EchoHost;
|
|
136
141
|
private readonly _invitationsManager: InvitationsManager;
|
|
137
142
|
private readonly _edgeConnection?: EdgeConnection = undefined;
|
|
143
|
+
private readonly _edgeHttpClient?: EdgeHttpClient = undefined;
|
|
138
144
|
private readonly _edgeFeatures?: Runtime.Client.EdgeFeatures = undefined;
|
|
139
145
|
private readonly _meshReplicator?: MeshEchoReplicator = undefined;
|
|
140
146
|
private readonly _echoEdgeReplicator?: EchoEdgeReplicator = undefined;
|
|
@@ -154,6 +160,7 @@ export class DataSpaceManager extends Resource {
|
|
|
154
160
|
this._edgeConnection = params.edgeConnection;
|
|
155
161
|
this._edgeFeatures = params.edgeFeatures;
|
|
156
162
|
this._echoEdgeReplicator = params.echoEdgeReplicator;
|
|
163
|
+
this._edgeHttpClient = params.edgeHttpClient;
|
|
157
164
|
this._runtimeParams = params.runtimeParams;
|
|
158
165
|
|
|
159
166
|
trace.diagnostic({
|
|
@@ -290,7 +297,7 @@ export class DataSpaceManager extends Resource {
|
|
|
290
297
|
},
|
|
291
298
|
};
|
|
292
299
|
|
|
293
|
-
const propertiesId =
|
|
300
|
+
const propertiesId = createObjectId();
|
|
294
301
|
document.change((doc: SpaceDoc) => {
|
|
295
302
|
setDeep(doc, ['objects', propertiesId], properties);
|
|
296
303
|
});
|
|
@@ -388,6 +395,26 @@ export class DataSpaceManager extends Resource {
|
|
|
388
395
|
});
|
|
389
396
|
}
|
|
390
397
|
|
|
398
|
+
async setSpaceEdgeReplicationSetting(spaceKey: PublicKey, setting: EdgeReplicationSetting) {
|
|
399
|
+
const space = this._spaces.get(spaceKey);
|
|
400
|
+
invariant(space, 'Space not found.');
|
|
401
|
+
|
|
402
|
+
await this._metadataStore.setSpaceEdgeReplicationSetting(spaceKey, setting);
|
|
403
|
+
|
|
404
|
+
if (space.isOpen) {
|
|
405
|
+
switch (setting) {
|
|
406
|
+
case EdgeReplicationSetting.DISABLED:
|
|
407
|
+
await this._echoEdgeReplicator?.disconnectFromSpace(space.id);
|
|
408
|
+
break;
|
|
409
|
+
case EdgeReplicationSetting.ENABLED:
|
|
410
|
+
await this._echoEdgeReplicator?.connectToSpace(space.id);
|
|
411
|
+
break;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
space.stateUpdate.emit();
|
|
416
|
+
}
|
|
417
|
+
|
|
391
418
|
private async _constructSpace(metadata: SpaceMetadata) {
|
|
392
419
|
log('construct space', { metadata });
|
|
393
420
|
const gossip = new Gossip({
|
|
@@ -479,13 +506,23 @@ export class DataSpaceManager extends Resource {
|
|
|
479
506
|
},
|
|
480
507
|
cache: metadata.cache,
|
|
481
508
|
edgeConnection: this._edgeConnection,
|
|
509
|
+
edgeHttpClient: this._edgeHttpClient,
|
|
482
510
|
edgeFeatures: this._edgeFeatures,
|
|
511
|
+
activeEdgeNotarizationPollingInterval: this._runtimeParams?.activeEdgeNotarizationPollingInterval,
|
|
483
512
|
});
|
|
484
513
|
dataSpace.postOpen.append(async () => {
|
|
485
|
-
|
|
514
|
+
const setting = dataSpace.getEdgeReplicationSetting();
|
|
515
|
+
if (setting === EdgeReplicationSetting.ENABLED) {
|
|
516
|
+
await this._echoEdgeReplicator?.connectToSpace(dataSpace.id);
|
|
517
|
+
} else if (this._echoEdgeReplicator) {
|
|
518
|
+
log('not connecting EchoEdgeReplicator because of EdgeReplicationSetting', { spaceId: dataSpace.id });
|
|
519
|
+
}
|
|
486
520
|
});
|
|
487
521
|
dataSpace.preClose.append(async () => {
|
|
488
|
-
|
|
522
|
+
const setting = dataSpace.getEdgeReplicationSetting();
|
|
523
|
+
if (setting === EdgeReplicationSetting.ENABLED) {
|
|
524
|
+
await this._echoEdgeReplicator?.disconnectFromSpace(dataSpace.id);
|
|
525
|
+
}
|
|
489
526
|
});
|
|
490
527
|
|
|
491
528
|
presence.newPeer.on((peerState) => {
|
|
@@ -7,10 +7,15 @@ 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
|
-
|
|
10
|
+
import {
|
|
11
|
+
type EchoHost,
|
|
12
|
+
type DatabaseRoot,
|
|
13
|
+
createMappedFeedWriter,
|
|
14
|
+
type MetadataStore,
|
|
15
|
+
type Space,
|
|
16
|
+
} from '@dxos/echo-pipeline';
|
|
12
17
|
import { SpaceDocVersion } from '@dxos/echo-protocol';
|
|
13
|
-
import type { EdgeConnection } from '@dxos/edge-client';
|
|
18
|
+
import type { EdgeConnection, EdgeHttpClient } from '@dxos/edge-client';
|
|
14
19
|
import { type FeedStore, type FeedWrapper } from '@dxos/feed-store';
|
|
15
20
|
import { failedInvariant } from '@dxos/invariant';
|
|
16
21
|
import { type Keyring } from '@dxos/keyring';
|
|
@@ -75,7 +80,9 @@ export type DataSpaceParams = {
|
|
|
75
80
|
callbacks?: DataSpaceCallbacks;
|
|
76
81
|
cache?: SpaceCache;
|
|
77
82
|
edgeConnection?: EdgeConnection;
|
|
83
|
+
edgeHttpClient?: EdgeHttpClient;
|
|
78
84
|
edgeFeatures?: Runtime.Client.EdgeFeatures;
|
|
85
|
+
activeEdgeNotarizationPollingInterval?: number;
|
|
79
86
|
};
|
|
80
87
|
|
|
81
88
|
export type CreateEpochOptions = {
|
|
@@ -96,7 +103,7 @@ export class DataSpace {
|
|
|
96
103
|
private readonly _feedStore: FeedStore<FeedMessage>;
|
|
97
104
|
private readonly _metadataStore: MetadataStore;
|
|
98
105
|
private readonly _signingContext: SigningContext;
|
|
99
|
-
private readonly _notarizationPlugin
|
|
106
|
+
private readonly _notarizationPlugin: NotarizationPlugin;
|
|
100
107
|
private readonly _callbacks: DataSpaceCallbacks;
|
|
101
108
|
private readonly _cache?: SpaceCache = undefined;
|
|
102
109
|
private readonly _echoHost: EchoHost;
|
|
@@ -136,6 +143,12 @@ export class DataSpace {
|
|
|
136
143
|
this._signingContext = params.signingContext;
|
|
137
144
|
this._callbacks = params.callbacks ?? {};
|
|
138
145
|
this._echoHost = params.echoHost;
|
|
146
|
+
this._notarizationPlugin = new NotarizationPlugin({
|
|
147
|
+
spaceId: this._inner.id,
|
|
148
|
+
edgeClient: params.edgeHttpClient,
|
|
149
|
+
edgeFeatures: params.edgeFeatures,
|
|
150
|
+
activeEdgePollingInterval: params.activeEdgeNotarizationPollingInterval,
|
|
151
|
+
});
|
|
139
152
|
|
|
140
153
|
this.authVerifier = new TrustedKeySetAuthVerifier({
|
|
141
154
|
trustedKeysProvider: () =>
|
|
@@ -231,6 +244,7 @@ export class DataSpace {
|
|
|
231
244
|
}
|
|
232
245
|
|
|
233
246
|
await this._inner.open(new Context());
|
|
247
|
+
await this._inner.startProtocol();
|
|
234
248
|
|
|
235
249
|
await this._edgeFeedReplicator?.open();
|
|
236
250
|
|
|
@@ -318,6 +332,7 @@ export class DataSpace {
|
|
|
318
332
|
this._state = SpaceState.SPACE_INITIALIZING;
|
|
319
333
|
log('new state', { state: SpaceState[this._state] });
|
|
320
334
|
|
|
335
|
+
log('initializing control pipeline');
|
|
321
336
|
await this._initializeAndReadControlPipeline();
|
|
322
337
|
|
|
323
338
|
// Allow other tasks to run before loading the data pipeline.
|
|
@@ -325,10 +340,13 @@ export class DataSpace {
|
|
|
325
340
|
|
|
326
341
|
const ready = this.stateUpdate.waitForCondition(() => this._state === SpaceState.SPACE_READY);
|
|
327
342
|
|
|
343
|
+
log('initializing automerge root');
|
|
328
344
|
this._automergeSpaceState.startProcessingRootDocs();
|
|
329
345
|
|
|
330
346
|
// TODO(dmaretskyi): Change so `initializeDataPipeline` doesn't wait for the space to be READY, but rather any state with a valid root.
|
|
347
|
+
log('waiting for space to be ready');
|
|
331
348
|
await ready;
|
|
349
|
+
log('space is ready');
|
|
332
350
|
}
|
|
333
351
|
|
|
334
352
|
private async _enterReadyState() {
|
|
@@ -345,6 +363,7 @@ export class DataSpace {
|
|
|
345
363
|
private async _initializeAndReadControlPipeline() {
|
|
346
364
|
await this._inner.controlPipeline.state.waitUntilReachedTargetTimeframe({
|
|
347
365
|
ctx: this._ctx,
|
|
366
|
+
timeout: 10_000,
|
|
348
367
|
breakOnStall: false,
|
|
349
368
|
});
|
|
350
369
|
|
|
@@ -408,8 +427,16 @@ export class DataSpace {
|
|
|
408
427
|
}
|
|
409
428
|
|
|
410
429
|
if (credentials.length > 0) {
|
|
411
|
-
|
|
412
|
-
|
|
430
|
+
try {
|
|
431
|
+
log('will notarize credentials for feed admission', { count: credentials.length });
|
|
432
|
+
// Never times out
|
|
433
|
+
await this.notarizationPlugin.notarize({ ctx: this._ctx, credentials, timeout: 0 });
|
|
434
|
+
|
|
435
|
+
log('credentials notarized');
|
|
436
|
+
} catch (err) {
|
|
437
|
+
log.error('error notarizing credentials for feed admission', err);
|
|
438
|
+
throw err;
|
|
439
|
+
}
|
|
413
440
|
|
|
414
441
|
// Set this after credentials are notarized so that on failure we will retry.
|
|
415
442
|
await this._metadataStore.setWritableFeedKeys(this.key, this.inner.controlFeedKey!, this.inner.dataFeedKey!);
|
|
@@ -546,6 +573,10 @@ export class DataSpace {
|
|
|
546
573
|
this.stateUpdate.emit();
|
|
547
574
|
}
|
|
548
575
|
|
|
576
|
+
getEdgeReplicationSetting() {
|
|
577
|
+
return this._metadataStore.getSpaceEdgeReplicationSetting(this.key);
|
|
578
|
+
}
|
|
579
|
+
|
|
549
580
|
private _onFeedAdded = async (feed: FeedWrapper<any>) => {
|
|
550
581
|
await this._edgeFeedReplicator!.addFeed(feed);
|
|
551
582
|
};
|