@dxos/client-services 0.8.4-main.c85a9c8dae → 0.8.4-main.d05539e30a
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/LICENSE +102 -5
- package/README.md +1 -1
- package/dist/lib/browser/{chunk-MQ6PWJ76.mjs → chunk-NGONP3EI.mjs} +1640 -3097
- package/dist/lib/browser/chunk-NGONP3EI.mjs.map +7 -0
- package/dist/lib/browser/{chunk-NQSC7HOE.mjs → chunk-XJRPB3GA.mjs} +1 -1
- package/dist/lib/browser/index.mjs +106 -194
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/packlets/diagnostics/browser-diagnostics-broadcast.mjs +1 -6
- package/dist/lib/browser/packlets/diagnostics/browser-diagnostics-broadcast.mjs.map +2 -2
- package/dist/lib/browser/packlets/diagnostics/diagnostics-broadcast.mjs +1 -1
- package/dist/lib/browser/packlets/locks/browser.mjs +9 -49
- package/dist/lib/browser/packlets/locks/browser.mjs.map +2 -2
- package/dist/lib/browser/packlets/locks/node.mjs +4 -22
- package/dist/lib/browser/packlets/locks/node.mjs.map +2 -2
- package/dist/lib/browser/testing/index.mjs +9 -22
- package/dist/lib/browser/testing/index.mjs.map +3 -3
- package/dist/lib/node-esm/{chunk-PKEGMOQ4.mjs → chunk-2DT3MZRL.mjs} +1 -1
- package/dist/lib/node-esm/{chunk-GUAL4U7S.mjs → chunk-OAECSUV2.mjs} +1640 -3097
- package/dist/lib/node-esm/chunk-OAECSUV2.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +106 -194
- package/dist/lib/node-esm/index.mjs.map +3 -3
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/packlets/diagnostics/browser-diagnostics-broadcast.mjs +1 -6
- package/dist/lib/node-esm/packlets/diagnostics/browser-diagnostics-broadcast.mjs.map +2 -2
- package/dist/lib/node-esm/packlets/diagnostics/diagnostics-broadcast.mjs +1 -1
- package/dist/lib/node-esm/packlets/locks/browser.mjs +9 -49
- package/dist/lib/node-esm/packlets/locks/browser.mjs.map +2 -2
- package/dist/lib/node-esm/packlets/locks/node.mjs +4 -22
- package/dist/lib/node-esm/packlets/locks/node.mjs.map +2 -2
- package/dist/lib/node-esm/testing/index.mjs +9 -22
- package/dist/lib/node-esm/testing/index.mjs.map +3 -3
- 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 +3 -2
- package/dist/types/src/packlets/agents/edge-agent-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/agents/edge-agent-service.d.ts +2 -1
- package/dist/types/src/packlets/agents/edge-agent-service.d.ts.map +1 -1
- package/dist/types/src/packlets/devices/devices-service.d.ts.map +1 -1
- package/dist/types/src/packlets/devtools/devtools.d.ts.map +1 -1
- package/dist/types/src/packlets/devtools/feeds.d.ts.map +1 -1
- package/dist/types/src/packlets/devtools/keys.d.ts.map +1 -1
- package/dist/types/src/packlets/devtools/metadata.d.ts.map +1 -1
- package/dist/types/src/packlets/devtools/network.d.ts.map +1 -1
- package/dist/types/src/packlets/devtools/spaces.d.ts.map +1 -1
- package/dist/types/src/packlets/diagnostics/browser-diagnostics-broadcast.d.ts.map +1 -1
- package/dist/types/src/packlets/diagnostics/diagnostics-broadcast.d.ts.map +1 -1
- package/dist/types/src/packlets/diagnostics/diagnostics-collector.d.ts.map +1 -1
- package/dist/types/src/packlets/diagnostics/diagnostics.d.ts +2 -3
- package/dist/types/src/packlets/diagnostics/diagnostics.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/authenticator.d.ts.map +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 +3 -3
- package/dist/types/src/packlets/identity/identity-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts +6 -5
- package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity-service.d.ts +6 -10
- package/dist/types/src/packlets/identity/identity-service.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity.d.ts +6 -9
- package/dist/types/src/packlets/identity/identity.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts +2 -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 +1 -1
- package/dist/types/src/packlets/invitations/edge-invitation-handler.d.ts.map +1 -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.map +1 -1
- package/dist/types/src/packlets/invitations/invitation-protocol.d.ts +5 -1
- package/dist/types/src/packlets/invitations/invitation-protocol.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitation-state.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitation-topology.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitations-handler.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitations-manager.d.ts +3 -3
- package/dist/types/src/packlets/invitations/invitations-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitations-service.d.ts +3 -3
- package/dist/types/src/packlets/invitations/invitations-service.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts +2 -1
- package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/utils.d.ts.map +1 -1
- package/dist/types/src/packlets/locks/browser.d.ts.map +1 -1
- package/dist/types/src/packlets/locks/node.d.ts.map +1 -1
- package/dist/types/src/packlets/logging/logging-service.d.ts.map +1 -1
- package/dist/types/src/packlets/network/network-service.d.ts +5 -4
- package/dist/types/src/packlets/network/network-service.d.ts.map +1 -1
- package/dist/types/src/packlets/services/client-rpc-server.d.ts +3 -3
- package/dist/types/src/packlets/services/client-rpc-server.d.ts.map +1 -1
- package/dist/types/src/packlets/services/feed-syncer.d.ts +2 -2
- package/dist/types/src/packlets/services/feed-syncer.d.ts.map +1 -1
- package/dist/types/src/packlets/services/service-context.d.ts +2 -3
- package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
- package/dist/types/src/packlets/services/service-host.d.ts +2 -3
- package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
- package/dist/types/src/packlets/services/service-registry.d.ts.map +1 -1
- package/dist/types/src/packlets/services/util.d.ts.map +1 -1
- package/dist/types/src/packlets/space-export/archive-format.d.ts +9 -0
- package/dist/types/src/packlets/space-export/archive-format.d.ts.map +1 -0
- package/dist/types/src/packlets/space-export/index.d.ts +4 -1
- package/dist/types/src/packlets/space-export/index.d.ts.map +1 -1
- package/dist/types/src/packlets/space-export/serialized-space-reader.d.ts +23 -0
- package/dist/types/src/packlets/space-export/serialized-space-reader.d.ts.map +1 -0
- package/dist/types/src/packlets/space-export/serialized-space-writer.d.ts +36 -0
- package/dist/types/src/packlets/space-export/serialized-space-writer.d.ts.map +1 -0
- package/dist/types/src/packlets/space-export/space-archive-reader.d.ts +9 -1
- package/dist/types/src/packlets/space-export/space-archive-reader.d.ts.map +1 -1
- package/dist/types/src/packlets/space-export/space-archive-writer.d.ts +7 -1
- package/dist/types/src/packlets/space-export/space-archive-writer.d.ts.map +1 -1
- package/dist/types/src/packlets/space-export/space-archive.test.d.ts +2 -0
- package/dist/types/src/packlets/space-export/space-archive.test.d.ts.map +1 -0
- package/dist/types/src/packlets/spaces/automerge-space-state.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/data-space-manager.d.ts +20 -14
- package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/data-space.d.ts +24 -7
- package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/epoch-migrations.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/genesis.d.ts +2 -1
- package/dist/types/src/packlets/spaces/genesis.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/notarization-plugin.d.ts +1 -4
- package/dist/types/src/packlets/spaces/notarization-plugin.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/spaces-service.d.ts +10 -7
- package/dist/types/src/packlets/spaces/spaces-service.d.ts.map +1 -1
- package/dist/types/src/packlets/storage/level.d.ts.map +1 -1
- package/dist/types/src/packlets/storage/profile-archive.d.ts.map +1 -1
- package/dist/types/src/packlets/storage/storage.d.ts.map +1 -1
- package/dist/types/src/packlets/storage/util.d.ts.map +1 -1
- package/dist/types/src/packlets/system/system-service.d.ts +1 -1
- package/dist/types/src/packlets/system/system-service.d.ts.map +1 -1
- package/dist/types/src/packlets/testing/credential-utils.d.ts.map +1 -1
- package/dist/types/src/packlets/testing/invitation-utils.d.ts.map +1 -1
- package/dist/types/src/packlets/testing/test-builder.d.ts.map +1 -1
- package/dist/types/src/packlets/worker/worker-runtime.d.ts +11 -1
- package/dist/types/src/packlets/worker/worker-runtime.d.ts.map +1 -1
- package/dist/types/src/packlets/worker/worker-session.d.ts +0 -2
- package/dist/types/src/packlets/worker/worker-session.d.ts.map +1 -1
- package/dist/types/src/testing/setup.d.ts.map +1 -1
- package/dist/types/src/version.d.ts +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +43 -50
- package/src/index.ts +1 -0
- package/src/packlets/agents/edge-agent-manager.ts +8 -5
- package/src/packlets/agents/edge-agent-service.ts +4 -2
- package/src/packlets/devices/devices-service.test.ts +0 -1
- package/src/packlets/devtools/devtools.ts +0 -1
- package/src/packlets/diagnostics/diagnostics.ts +1 -2
- package/src/packlets/identity/contacts-service.ts +0 -1
- package/src/packlets/identity/identity-manager.test.ts +5 -5
- package/src/packlets/identity/identity-manager.ts +18 -17
- package/src/packlets/identity/identity-recovery-manager.ts +20 -16
- package/src/packlets/identity/identity-service.test.ts +6 -27
- package/src/packlets/identity/identity-service.ts +13 -81
- package/src/packlets/identity/identity.test.ts +2 -2
- package/src/packlets/identity/identity.ts +9 -32
- package/src/packlets/invitations/device-invitation-protocol.ts +3 -2
- package/src/packlets/invitations/edge-invitation-handler.ts +9 -5
- package/src/packlets/invitations/invitation-host-extension.ts +7 -10
- package/src/packlets/invitations/invitation-protocol.ts +5 -1
- package/src/packlets/invitations/invitation-state.ts +1 -15
- package/src/packlets/invitations/invitations-handler.test.ts +4 -5
- package/src/packlets/invitations/invitations-handler.ts +67 -15
- package/src/packlets/invitations/invitations-manager.ts +40 -15
- package/src/packlets/invitations/invitations-service.ts +9 -9
- package/src/packlets/invitations/space-invitation-protocol.test.ts +17 -16
- package/src/packlets/invitations/space-invitation-protocol.ts +4 -3
- package/src/packlets/logging/logging-service.ts +15 -15
- package/src/packlets/network/network-service.test.ts +0 -1
- package/src/packlets/network/network-service.ts +10 -8
- package/src/packlets/services/client-rpc-server.ts +15 -12
- package/src/packlets/services/feed-syncer.test.ts +3 -3
- package/src/packlets/services/feed-syncer.ts +67 -20
- package/src/packlets/services/service-context.test.ts +3 -2
- package/src/packlets/services/service-context.ts +106 -46
- package/src/packlets/services/service-host.test.ts +8 -8
- package/src/packlets/services/service-host.ts +17 -24
- package/src/packlets/services/service-registry.test.ts +0 -1
- package/src/packlets/space-export/archive-format.ts +42 -0
- package/src/packlets/space-export/index.ts +4 -1
- package/src/packlets/space-export/serialized-space-reader.ts +111 -0
- package/src/packlets/space-export/serialized-space-writer.ts +252 -0
- package/src/packlets/space-export/space-archive-reader.ts +64 -3
- package/src/packlets/space-export/space-archive-writer.ts +38 -2
- package/src/packlets/space-export/space-archive.test.ts +461 -0
- package/src/packlets/spaces/data-space-manager.test.ts +79 -13
- package/src/packlets/spaces/data-space-manager.ts +80 -115
- package/src/packlets/spaces/data-space.ts +55 -31
- package/src/packlets/spaces/edge-feed-replicator.test.ts +1 -1
- package/src/packlets/spaces/edge-feed-replicator.ts +9 -7
- package/src/packlets/spaces/epoch-migrations.ts +4 -3
- package/src/packlets/spaces/genesis.ts +6 -1
- package/src/packlets/spaces/notarization-plugin.ts +2 -1
- package/src/packlets/spaces/spaces-service.test.ts +18 -11
- package/src/packlets/spaces/spaces-service.ts +115 -17
- package/src/packlets/testing/invitation-utils.ts +3 -2
- package/src/packlets/worker/worker-runtime.ts +39 -6
- package/src/packlets/worker/worker-session.ts +4 -10
- package/src/version.ts +1 -1
- package/dist/lib/browser/chunk-MQ6PWJ76.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-GUAL4U7S.mjs.map +0 -7
- package/dist/types/src/packlets/identity/default-space-state-machine.d.ts +0 -19
- package/dist/types/src/packlets/identity/default-space-state-machine.d.ts.map +0 -1
- package/src/packlets/identity/default-space-state-machine.ts +0 -44
- /package/dist/lib/browser/{chunk-NQSC7HOE.mjs.map → chunk-XJRPB3GA.mjs.map} +0 -0
- /package/dist/lib/node-esm/{chunk-PKEGMOQ4.mjs.map → chunk-2DT3MZRL.mjs.map} +0 -0
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import { describe, expect, test } from 'vitest';
|
|
6
6
|
|
|
7
7
|
import { asyncTimeout, latch } from '@dxos/async';
|
|
8
|
+
import { Context } from '@dxos/context';
|
|
8
9
|
import { createAdmissionCredentials } from '@dxos/credentials';
|
|
9
10
|
import { AuthStatus } from '@dxos/echo-pipeline';
|
|
10
11
|
import { writeMessages } from '@dxos/feed-store';
|
|
@@ -22,7 +23,7 @@ describe('DataSpaceManager', () => {
|
|
|
22
23
|
await peer.createIdentity();
|
|
23
24
|
await openAndClose(peer.echoHost, peer.dataSpaceManager);
|
|
24
25
|
|
|
25
|
-
const space = await peer.dataSpaceManager.createSpace();
|
|
26
|
+
const space = await peer.dataSpaceManager.createSpace(new Context());
|
|
26
27
|
|
|
27
28
|
// Process all written mutations.
|
|
28
29
|
await space.inner.controlPipeline.state.waitUntilTimeframe(space.inner.controlPipeline.state.endTimeframe);
|
|
@@ -45,7 +46,7 @@ describe('DataSpaceManager', () => {
|
|
|
45
46
|
await openAndClose(peer1.echoHost, peer1.dataSpaceManager, peer2.echoHost, peer2.dataSpaceManager);
|
|
46
47
|
await connectReplicators([peer1, peer2]);
|
|
47
48
|
|
|
48
|
-
const space1 = await peer1.dataSpaceManager.createSpace();
|
|
49
|
+
const space1 = await peer1.dataSpaceManager.createSpace(new Context());
|
|
49
50
|
await space1.inner.controlPipeline.state.waitUntilTimeframe(space1.inner.controlPipeline.state.endTimeframe);
|
|
50
51
|
|
|
51
52
|
// Admit peer2 to space1.
|
|
@@ -60,7 +61,7 @@ describe('DataSpaceManager', () => {
|
|
|
60
61
|
);
|
|
61
62
|
|
|
62
63
|
// Accept must be called after admission so that the peer can authenticate for notarization.
|
|
63
|
-
const space2 = await peer2.dataSpaceManager.acceptSpace({
|
|
64
|
+
const space2 = await peer2.dataSpaceManager.acceptSpace(new Context(), {
|
|
64
65
|
spaceKey: space1.key,
|
|
65
66
|
genesisFeedKey: space1.inner.genesisFeedKey,
|
|
66
67
|
});
|
|
@@ -115,7 +116,7 @@ describe('DataSpaceManager', () => {
|
|
|
115
116
|
await openAndClose(peer1.echoHost, peer1.dataSpaceManager, peer2.echoHost, peer2.dataSpaceManager);
|
|
116
117
|
await connectReplicators([peer1, peer2]);
|
|
117
118
|
|
|
118
|
-
const space1 = await peer1.dataSpaceManager.createSpace();
|
|
119
|
+
const space1 = await peer1.dataSpaceManager.createSpace(new Context());
|
|
119
120
|
await space1.inner.controlPipeline.state.waitUntilTimeframe(space1.inner.controlPipeline.state.endTimeframe);
|
|
120
121
|
|
|
121
122
|
// Admit peer2 to space1.
|
|
@@ -130,7 +131,7 @@ describe('DataSpaceManager', () => {
|
|
|
130
131
|
);
|
|
131
132
|
|
|
132
133
|
// Accept must be called after admission so that the peer can authenticate for notarization.
|
|
133
|
-
const space2 = await peer2.dataSpaceManager.acceptSpace({
|
|
134
|
+
const space2 = await peer2.dataSpaceManager.acceptSpace(new Context(), {
|
|
134
135
|
spaceKey: space1.key,
|
|
135
136
|
genesisFeedKey: space1.inner.genesisFeedKey,
|
|
136
137
|
});
|
|
@@ -149,6 +150,71 @@ describe('DataSpaceManager', () => {
|
|
|
149
150
|
await receivedMessage();
|
|
150
151
|
});
|
|
151
152
|
|
|
153
|
+
test('create space with tags', async () => {
|
|
154
|
+
const builder = new TestBuilder();
|
|
155
|
+
const peer = builder.createPeer();
|
|
156
|
+
await peer.createIdentity();
|
|
157
|
+
await openAndClose(peer.echoHost, peer.dataSpaceManager);
|
|
158
|
+
|
|
159
|
+
const space = await peer.dataSpaceManager.createSpace(new Context(), { tags: ['personal', 'test'] });
|
|
160
|
+
await space.inner.controlPipeline.state.waitUntilTimeframe(space.inner.controlPipeline.state.endTimeframe);
|
|
161
|
+
|
|
162
|
+
expect(space.inner.spaceState.tags).toEqual(['personal', 'test']);
|
|
163
|
+
expect(space.inner.spaceState.genesisCredential).to.exist;
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
test('create space without tags has empty tags', async () => {
|
|
167
|
+
const builder = new TestBuilder();
|
|
168
|
+
const peer = builder.createPeer();
|
|
169
|
+
await peer.createIdentity();
|
|
170
|
+
await openAndClose(peer.echoHost, peer.dataSpaceManager);
|
|
171
|
+
|
|
172
|
+
const space = await peer.dataSpaceManager.createSpace(new Context());
|
|
173
|
+
await space.inner.controlPipeline.state.waitUntilTimeframe(space.inner.controlPipeline.state.endTimeframe);
|
|
174
|
+
|
|
175
|
+
expect(space.inner.spaceState.tags).toEqual([]);
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
test('tags propagate through peer admission', async () => {
|
|
179
|
+
const builder = new TestBuilder();
|
|
180
|
+
const peer1 = builder.createPeer();
|
|
181
|
+
await peer1.createIdentity();
|
|
182
|
+
const peer2 = builder.createPeer();
|
|
183
|
+
await peer2.createIdentity();
|
|
184
|
+
|
|
185
|
+
await openAndClose(peer1.echoHost, peer1.dataSpaceManager, peer2.echoHost, peer2.dataSpaceManager);
|
|
186
|
+
await connectReplicators([peer1, peer2]);
|
|
187
|
+
|
|
188
|
+
const space1 = await peer1.dataSpaceManager.createSpace(new Context(), { tags: ['personal'] });
|
|
189
|
+
await space1.inner.controlPipeline.state.waitUntilTimeframe(space1.inner.controlPipeline.state.endTimeframe);
|
|
190
|
+
|
|
191
|
+
// Admit peer2 to space1.
|
|
192
|
+
await writeMessages(
|
|
193
|
+
space1.inner.controlPipeline.writer,
|
|
194
|
+
await createAdmissionCredentials(
|
|
195
|
+
peer1.identity.credentialSigner,
|
|
196
|
+
peer2.identity.identityKey,
|
|
197
|
+
space1.key,
|
|
198
|
+
space1.inner.genesisFeedKey,
|
|
199
|
+
undefined, // role (default ADMIN)
|
|
200
|
+
undefined, // membershipChainHeads
|
|
201
|
+
undefined, // profile
|
|
202
|
+
undefined, // invitationCredentialId
|
|
203
|
+
space1.inner.spaceState.tags, // tags
|
|
204
|
+
),
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
const space2 = await peer2.dataSpaceManager.acceptSpace(new Context(), {
|
|
208
|
+
spaceKey: space1.key,
|
|
209
|
+
genesisFeedKey: space1.inner.genesisFeedKey,
|
|
210
|
+
tags: space1.inner.spaceState.tags,
|
|
211
|
+
});
|
|
212
|
+
await peer2.dataSpaceManager.waitUntilSpaceReady(space2.key);
|
|
213
|
+
|
|
214
|
+
// Peer2's space should have the same tags.
|
|
215
|
+
expect(space2.inner.spaceState.tags).toEqual(['personal']);
|
|
216
|
+
});
|
|
217
|
+
|
|
152
218
|
describe('activation', () => {
|
|
153
219
|
test('can activate and deactivate a space', async () => {
|
|
154
220
|
const builder = new TestBuilder();
|
|
@@ -157,14 +223,14 @@ describe('DataSpaceManager', () => {
|
|
|
157
223
|
await peer.createIdentity();
|
|
158
224
|
await openAndClose(peer.echoHost, peer.dataSpaceManager);
|
|
159
225
|
|
|
160
|
-
const space = await peer.dataSpaceManager.createSpace();
|
|
226
|
+
const space = await peer.dataSpaceManager.createSpace(new Context());
|
|
161
227
|
await space.inner.controlPipeline.state.waitUntilTimeframe(space.inner.controlPipeline.state.endTimeframe);
|
|
162
228
|
expect(space.state).to.equal(SpaceState.SPACE_READY);
|
|
163
229
|
|
|
164
|
-
await space.deactivate();
|
|
230
|
+
await space.deactivate(new Context());
|
|
165
231
|
expect(space.state).to.equal(SpaceState.SPACE_INACTIVE);
|
|
166
232
|
|
|
167
|
-
await space.activate();
|
|
233
|
+
await space.activate(new Context());
|
|
168
234
|
await asyncTimeout(
|
|
169
235
|
space.stateUpdate.waitForCondition(() => space.state === SpaceState.SPACE_READY),
|
|
170
236
|
500,
|
|
@@ -178,12 +244,12 @@ describe('DataSpaceManager', () => {
|
|
|
178
244
|
await peer.createIdentity();
|
|
179
245
|
await openAndClose(peer.echoHost, peer.dataSpaceManager);
|
|
180
246
|
|
|
181
|
-
await peer.dataSpaceManager.createSpace();
|
|
247
|
+
await peer.dataSpaceManager.createSpace(new Context());
|
|
182
248
|
await reloadDataSpaces(peer);
|
|
183
249
|
|
|
184
250
|
const space = getFirstSpace(peer);
|
|
185
251
|
expect(space.state).to.equal(SpaceState.SPACE_CLOSED);
|
|
186
|
-
await space.activate();
|
|
252
|
+
await space.activate(new Context());
|
|
187
253
|
await asyncTimeout(
|
|
188
254
|
space.stateUpdate.waitForCondition(() => space.state === SpaceState.SPACE_READY),
|
|
189
255
|
500,
|
|
@@ -197,10 +263,10 @@ describe('DataSpaceManager', () => {
|
|
|
197
263
|
await peer.createIdentity();
|
|
198
264
|
await openAndClose(peer.echoHost, peer.dataSpaceManager);
|
|
199
265
|
|
|
200
|
-
await peer.dataSpaceManager.createSpace();
|
|
266
|
+
await peer.dataSpaceManager.createSpace(new Context());
|
|
201
267
|
await reloadDataSpaces(peer);
|
|
202
268
|
|
|
203
|
-
await getFirstSpace(peer).deactivate();
|
|
269
|
+
await getFirstSpace(peer).deactivate(new Context());
|
|
204
270
|
|
|
205
271
|
await reloadDataSpaces(peer);
|
|
206
272
|
|
|
@@ -209,7 +275,7 @@ describe('DataSpaceManager', () => {
|
|
|
209
275
|
});
|
|
210
276
|
|
|
211
277
|
const connectReplicators = (peers: TestPeer[]) => {
|
|
212
|
-
return Promise.all(peers.map((peer) => peer.echoHost.addReplicator(peer.meshEchoReplicator)));
|
|
278
|
+
return Promise.all(peers.map((peer) => peer.echoHost.addReplicator(Context.default(), peer.meshEchoReplicator)));
|
|
213
279
|
};
|
|
214
280
|
|
|
215
281
|
const reloadDataSpaces = async (peer: TestPeer) => {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { type Doc } from '@automerge/automerge';
|
|
6
|
-
import { type AutomergeUrl, type
|
|
6
|
+
import { type AutomergeUrl, type DocumentId, interpretAsDocumentId } from '@automerge/automerge-repo';
|
|
7
7
|
|
|
8
8
|
import { Event, synchronized, trackLeaks } from '@dxos/async';
|
|
9
9
|
import { SpaceProperties } from '@dxos/client-protocol';
|
|
@@ -16,13 +16,12 @@ import {
|
|
|
16
16
|
getCredentialAssertion,
|
|
17
17
|
} from '@dxos/credentials';
|
|
18
18
|
import { Type } from '@dxos/echo';
|
|
19
|
-
import { getSchemaDXN } from '@dxos/echo/internal';
|
|
20
19
|
import {
|
|
21
20
|
AuthStatus,
|
|
22
21
|
CredentialServerExtension,
|
|
23
22
|
DatabaseRoot,
|
|
24
|
-
type EchoEdgeReplicator,
|
|
25
23
|
type EchoHost,
|
|
24
|
+
type EdgeAutomergeReplicator,
|
|
26
25
|
type MeshEchoReplicator,
|
|
27
26
|
type MetadataStore,
|
|
28
27
|
type Space,
|
|
@@ -31,45 +30,40 @@ import {
|
|
|
31
30
|
type SpaceProtocolSession,
|
|
32
31
|
findInlineObjectOfType,
|
|
33
32
|
} from '@dxos/echo-pipeline';
|
|
34
|
-
import {
|
|
35
|
-
type DatabaseDirectory,
|
|
36
|
-
EncodedReference,
|
|
37
|
-
type ObjectStructure,
|
|
38
|
-
SpaceDocVersion,
|
|
39
|
-
createIdFromSpaceKey,
|
|
40
|
-
} from '@dxos/echo-protocol';
|
|
33
|
+
import { type DatabaseDirectory, createIdFromSpaceKey } from '@dxos/echo-protocol';
|
|
41
34
|
import type { EdgeConnection, EdgeHttpClient } from '@dxos/edge-client';
|
|
42
35
|
import { type FeedStore, writeMessages } from '@dxos/feed-store';
|
|
43
36
|
import { assertArgument, assertState, failedInvariant, invariant } from '@dxos/invariant';
|
|
44
37
|
import { type Keyring } from '@dxos/keyring';
|
|
45
|
-
import {
|
|
38
|
+
import { PublicKey, type SpaceId } from '@dxos/keys';
|
|
46
39
|
import { log } from '@dxos/log';
|
|
47
|
-
import { AlreadyJoinedError
|
|
40
|
+
import { AlreadyJoinedError } from '@dxos/protocols';
|
|
48
41
|
import { Invitation, SpaceState } from '@dxos/protocols/proto/dxos/client/services';
|
|
49
42
|
import { type Runtime } from '@dxos/protocols/proto/dxos/config';
|
|
50
43
|
import { type FeedMessage } from '@dxos/protocols/proto/dxos/echo/feed';
|
|
51
44
|
import { EdgeReplicationSetting, type SpaceMetadata } from '@dxos/protocols/proto/dxos/echo/metadata';
|
|
52
|
-
import {
|
|
45
|
+
import {
|
|
46
|
+
type Credential,
|
|
47
|
+
MembershipPolicy,
|
|
48
|
+
type ProfileDocument,
|
|
49
|
+
SpaceMember,
|
|
50
|
+
} from '@dxos/protocols/proto/dxos/halo/credentials';
|
|
53
51
|
import { type DelegateSpaceInvitation } from '@dxos/protocols/proto/dxos/halo/invitations';
|
|
54
52
|
import { type PeerState } from '@dxos/protocols/proto/dxos/mesh/presence';
|
|
55
53
|
import { type Teleport } from '@dxos/teleport';
|
|
56
54
|
import { Gossip, Presence } from '@dxos/teleport-extension-gossip';
|
|
57
55
|
import { type Timeframe } from '@dxos/timeframe';
|
|
58
56
|
import { trace } from '@dxos/tracing';
|
|
59
|
-
import { ComplexMap, deferFunction, forEachAsync
|
|
57
|
+
import { ComplexMap, deferFunction, forEachAsync } from '@dxos/util';
|
|
60
58
|
|
|
61
59
|
import { createAuthProvider } from '../identity';
|
|
62
60
|
import { type InvitationsManager } from '../invitations';
|
|
63
|
-
|
|
64
61
|
import { DataSpace } from './data-space';
|
|
65
62
|
import { spaceGenesis } from './genesis';
|
|
66
63
|
|
|
67
64
|
const PRESENCE_ANNOUNCE_INTERVAL = 10_000;
|
|
68
65
|
const PRESENCE_OFFLINE_TIMEOUT = 20_000;
|
|
69
66
|
|
|
70
|
-
// Space properties key for default metadata.
|
|
71
|
-
const DEFAULT_SPACE_KEY = '__DEFAULT__';
|
|
72
|
-
|
|
73
67
|
export interface SigningContext {
|
|
74
68
|
identityKey: PublicKey;
|
|
75
69
|
deviceKey: PublicKey;
|
|
@@ -94,6 +88,9 @@ export type AcceptSpaceOptions = {
|
|
|
94
88
|
* We will try to catch up to this timeframe before initializing the database.
|
|
95
89
|
*/
|
|
96
90
|
dataTimeframe?: Timeframe;
|
|
91
|
+
|
|
92
|
+
/** Tags assigned to the space member. */
|
|
93
|
+
tags?: string[];
|
|
97
94
|
};
|
|
98
95
|
|
|
99
96
|
export type AdmitMemberOptions = {
|
|
@@ -102,6 +99,7 @@ export type AdmitMemberOptions = {
|
|
|
102
99
|
role: SpaceMember.Role;
|
|
103
100
|
profile?: ProfileDocument;
|
|
104
101
|
delegationCredentialId?: PublicKey;
|
|
102
|
+
tags?: string[];
|
|
105
103
|
};
|
|
106
104
|
|
|
107
105
|
export type DataSpaceManagerProps = {
|
|
@@ -115,7 +113,7 @@ export type DataSpaceManagerProps = {
|
|
|
115
113
|
edgeConnection?: EdgeConnection;
|
|
116
114
|
edgeHttpClient?: EdgeHttpClient;
|
|
117
115
|
meshReplicator?: MeshEchoReplicator;
|
|
118
|
-
echoEdgeReplicator?:
|
|
116
|
+
echoEdgeReplicator?: EdgeAutomergeReplicator;
|
|
119
117
|
runtimeProps?: DataSpaceManagerRuntimeProps;
|
|
120
118
|
edgeFeatures?: Runtime.Client.EdgeFeatures;
|
|
121
119
|
};
|
|
@@ -135,16 +133,17 @@ export type DataSpaceManagerRuntimeProps = {
|
|
|
135
133
|
export type CreateSpaceOptions = {
|
|
136
134
|
rootUrl?: AutomergeUrl;
|
|
137
135
|
documents?: Record<DocumentId, Uint8Array>;
|
|
136
|
+
tags?: string[];
|
|
137
|
+
membershipPolicy?: MembershipPolicy;
|
|
138
138
|
};
|
|
139
139
|
|
|
140
140
|
@trackLeaks('open', 'close')
|
|
141
|
+
@trace.resource({ lifecycle: true })
|
|
141
142
|
export class DataSpaceManager extends Resource {
|
|
142
143
|
public readonly updated = new Event();
|
|
143
144
|
|
|
144
145
|
private readonly _spaces = new ComplexMap<PublicKey, DataSpace>(PublicKey.hash);
|
|
145
146
|
|
|
146
|
-
private readonly _instanceId = PublicKey.random().toHex();
|
|
147
|
-
|
|
148
147
|
private readonly _spaceManager: SpaceManager;
|
|
149
148
|
private readonly _metadataStore: MetadataStore;
|
|
150
149
|
private readonly _keyring: Keyring;
|
|
@@ -156,7 +155,7 @@ export class DataSpaceManager extends Resource {
|
|
|
156
155
|
private readonly _edgeHttpClient?: EdgeHttpClient = undefined;
|
|
157
156
|
private readonly _edgeFeatures?: Runtime.Client.EdgeFeatures = undefined;
|
|
158
157
|
private readonly _meshReplicator?: MeshEchoReplicator = undefined;
|
|
159
|
-
private readonly _echoEdgeReplicator?:
|
|
158
|
+
private readonly _echoEdgeReplicator?: EdgeAutomergeReplicator = undefined;
|
|
160
159
|
private readonly _runtimeProps?: DataSpaceManagerRuntimeProps = undefined;
|
|
161
160
|
|
|
162
161
|
constructor(params: DataSpaceManagerProps) {
|
|
@@ -184,9 +183,8 @@ export class DataSpaceManager extends Resource {
|
|
|
184
183
|
Array.from(this._spaces.values()).map(async (space) => {
|
|
185
184
|
const rootUrl = space.automergeSpaceState.rootUrl;
|
|
186
185
|
const rootHandle = rootUrl
|
|
187
|
-
? await this._echoHost.loadDoc<Doc<DatabaseDirectory>>(
|
|
186
|
+
? await this._echoHost.loadDoc<Doc<DatabaseDirectory>>(this._ctx, rootUrl as AutomergeUrl)
|
|
188
187
|
: undefined;
|
|
189
|
-
await rootHandle?.whenReady();
|
|
190
188
|
const rootDoc = rootHandle?.doc();
|
|
191
189
|
|
|
192
190
|
const properties = rootDoc && findInlineObjectOfType(rootDoc, Type.getTypename(SpaceProperties));
|
|
@@ -217,16 +215,16 @@ export class DataSpaceManager extends Resource {
|
|
|
217
215
|
}
|
|
218
216
|
|
|
219
217
|
@synchronized
|
|
220
|
-
|
|
218
|
+
@trace.span({ showInBrowserTimeline: true, op: 'lifecycle' })
|
|
219
|
+
protected override async _open(ctx: Context): Promise<void> {
|
|
221
220
|
log('open');
|
|
222
|
-
log.trace('dxos.echo.data-space-manager.open', Trace.begin({ id: this._instanceId }));
|
|
223
221
|
log('metadata loaded', { spaces: this._metadataStore.spaces.length });
|
|
224
222
|
|
|
225
223
|
const spacesToActivate: DataSpace[] = [];
|
|
226
224
|
await forEachAsync(this._metadataStore.spaces, async (spaceMetadata) => {
|
|
227
225
|
try {
|
|
228
226
|
log('load space', { spaceMetadata });
|
|
229
|
-
const space = await this._constructSpace(spaceMetadata);
|
|
227
|
+
const space = await this._constructSpace(ctx, spaceMetadata);
|
|
230
228
|
// Track spaces that were previously active for auto-activation (used in dedicated worker mode).
|
|
231
229
|
if (this._runtimeProps?.autoActivateSpaces && spaceMetadata.state === SpaceState.SPACE_ACTIVE) {
|
|
232
230
|
spacesToActivate.push(space);
|
|
@@ -239,21 +237,19 @@ export class DataSpaceManager extends Resource {
|
|
|
239
237
|
// Auto-activate spaces that were previously active (used in dedicated worker mode after leader changeover).
|
|
240
238
|
for (const space of spacesToActivate) {
|
|
241
239
|
log('auto-activating space', { spaceKey: space.key });
|
|
242
|
-
space.activate().catch((err) => {
|
|
240
|
+
space.activate(ctx).catch((err) => {
|
|
243
241
|
log.error('Error auto-activating space', { spaceKey: space.key, err });
|
|
244
242
|
});
|
|
245
243
|
}
|
|
246
244
|
|
|
247
245
|
this.updated.emit();
|
|
248
|
-
|
|
249
|
-
log.trace('dxos.echo.data-space-manager.open', Trace.end({ id: this._instanceId }));
|
|
250
246
|
}
|
|
251
247
|
|
|
252
248
|
@synchronized
|
|
253
|
-
protected override async _close(): Promise<void> {
|
|
249
|
+
protected override async _close(ctx: Context): Promise<void> {
|
|
254
250
|
log('close');
|
|
255
251
|
for (const space of this._spaces.values()) {
|
|
256
|
-
await space.close();
|
|
252
|
+
await space.close(ctx);
|
|
257
253
|
}
|
|
258
254
|
this._spaces.clear();
|
|
259
255
|
}
|
|
@@ -262,7 +258,8 @@ export class DataSpaceManager extends Resource {
|
|
|
262
258
|
* Creates a new space writing the genesis credentials to the control feed.
|
|
263
259
|
*/
|
|
264
260
|
@synchronized
|
|
265
|
-
|
|
261
|
+
@trace.span({ showInBrowserTimeline: true, op: 'lifecycle' })
|
|
262
|
+
async createSpace(ctx: Context, options: CreateSpaceOptions = {}): Promise<DataSpace> {
|
|
266
263
|
assertArgument(
|
|
267
264
|
!!options.rootUrl === !!options.documents,
|
|
268
265
|
'options',
|
|
@@ -270,6 +267,8 @@ export class DataSpaceManager extends Resource {
|
|
|
270
267
|
);
|
|
271
268
|
|
|
272
269
|
assertState(this._lifecycleState === LifecycleState.OPEN, 'Not open.');
|
|
270
|
+
|
|
271
|
+
const tags = options.tags ? Array.from(options.tags) : [];
|
|
273
272
|
const spaceKey = await this._keyring.createKey();
|
|
274
273
|
const controlFeedKey = await this._keyring.createKey();
|
|
275
274
|
const dataFeedKey = await this._keyring.createKey();
|
|
@@ -282,6 +281,7 @@ export class DataSpaceManager extends Resource {
|
|
|
282
281
|
controlFeedKey,
|
|
283
282
|
dataFeedKey,
|
|
284
283
|
state: SpaceState.SPACE_ACTIVE,
|
|
284
|
+
tags,
|
|
285
285
|
};
|
|
286
286
|
|
|
287
287
|
log('creating space...', { spaceId, spaceKey });
|
|
@@ -319,30 +319,38 @@ export class DataSpaceManager extends Resource {
|
|
|
319
319
|
let root: DatabaseRoot;
|
|
320
320
|
if (options.rootUrl) {
|
|
321
321
|
const newRootDocId = documentIdMapping[interpretAsDocumentId(options.rootUrl)] ?? failedInvariant();
|
|
322
|
-
const rootDocHandle = await this._echoHost.loadDoc<DatabaseDirectory>(
|
|
322
|
+
const rootDocHandle = await this._echoHost.loadDoc<DatabaseDirectory>(ctx, newRootDocId);
|
|
323
|
+
invariant(rootDocHandle, 'Root document must be available after import.');
|
|
323
324
|
DatabaseRoot.mapLinks(rootDocHandle, documentIdMapping);
|
|
324
325
|
|
|
325
|
-
root = await this._echoHost.openSpaceRoot(spaceId, `automerge:${newRootDocId}` as AutomergeUrl);
|
|
326
|
+
root = await this._echoHost.openSpaceRoot(ctx, spaceId, `automerge:${newRootDocId}` as AutomergeUrl);
|
|
326
327
|
} else {
|
|
327
|
-
root = await this._echoHost.createSpaceRoot(spaceKey);
|
|
328
|
+
root = await this._echoHost.createSpaceRoot(ctx, spaceKey);
|
|
328
329
|
}
|
|
329
|
-
await this._echoHost.flush();
|
|
330
|
+
await this._echoHost.flush(ctx);
|
|
330
331
|
|
|
331
332
|
log('constructing space...', { spaceKey });
|
|
332
333
|
|
|
333
|
-
const space = await this._constructSpace(metadata);
|
|
334
|
-
await space.open();
|
|
334
|
+
const space = await this._constructSpace(ctx, metadata);
|
|
335
|
+
await space.open(ctx);
|
|
335
336
|
|
|
336
337
|
log('adding space...', { spaceKey });
|
|
337
338
|
|
|
338
|
-
const credentials = await spaceGenesis(
|
|
339
|
+
const credentials = await spaceGenesis(
|
|
340
|
+
this._keyring,
|
|
341
|
+
this._signingContext,
|
|
342
|
+
space.inner,
|
|
343
|
+
root.url,
|
|
344
|
+
tags,
|
|
345
|
+
options.membershipPolicy,
|
|
346
|
+
);
|
|
339
347
|
await this._metadataStore.addSpace(metadata);
|
|
340
348
|
|
|
341
349
|
const memberCredential = credentials[1];
|
|
342
350
|
invariant(getCredentialAssertion(memberCredential)['@type'] === 'dxos.halo.credentials.SpaceMember');
|
|
343
351
|
await this._signingContext.recordCredential(memberCredential);
|
|
344
352
|
|
|
345
|
-
await space.initializeDataPipeline();
|
|
353
|
+
await space.initializeDataPipeline(ctx);
|
|
346
354
|
|
|
347
355
|
log('space ready.', { spaceId, spaceKey });
|
|
348
356
|
|
|
@@ -350,86 +358,36 @@ export class DataSpaceManager extends Resource {
|
|
|
350
358
|
return space;
|
|
351
359
|
}
|
|
352
360
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
case SpaceDocVersion.CURRENT: {
|
|
359
|
-
if (!space.databaseRoot.handle.isReady()) {
|
|
360
|
-
log.warn('waiting for space root to be ready', { spaceId: space.id });
|
|
361
|
-
await space.databaseRoot.handle.whenReady();
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
const [_, properties] =
|
|
365
|
-
findInlineObjectOfType(space.databaseRoot.doc()!, Type.getTypename(SpaceProperties)) ?? [];
|
|
366
|
-
return properties?.data?.[DEFAULT_SPACE_KEY] === this._signingContext.identityKey.toHex();
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
case SpaceDocVersion.LEGACY: {
|
|
370
|
-
throw new Error('Legacy space version is not supported');
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
default:
|
|
374
|
-
log.warn('unknown space version', { version: space.databaseRoot.getVersion(), spaceId: space.id });
|
|
375
|
-
return false;
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
async createDefaultSpace(): Promise<DataSpace> {
|
|
380
|
-
const space = await this.createSpace();
|
|
381
|
-
const document = await this._getSpaceRootDocument(space);
|
|
382
|
-
|
|
383
|
-
// TODO(dmaretskyi): Better API for low-level data access.
|
|
384
|
-
const properties: ObjectStructure = {
|
|
385
|
-
system: {
|
|
386
|
-
type: EncodedReference.fromDXN(getSchemaDXN(SpaceProperties)!),
|
|
387
|
-
},
|
|
388
|
-
data: {
|
|
389
|
-
[DEFAULT_SPACE_KEY]: this._signingContext.identityKey.toHex(),
|
|
390
|
-
},
|
|
391
|
-
meta: {
|
|
392
|
-
keys: [],
|
|
393
|
-
},
|
|
394
|
-
};
|
|
395
|
-
|
|
396
|
-
const propertiesId = ObjectId.random();
|
|
397
|
-
document.change((doc: DatabaseDirectory) => {
|
|
398
|
-
setDeep(doc, ['objects', propertiesId], properties);
|
|
399
|
-
});
|
|
400
|
-
|
|
401
|
-
await this._echoHost.flush();
|
|
402
|
-
return space;
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
private async _getSpaceRootDocument(space: DataSpace): Promise<DocHandle<DatabaseDirectory>> {
|
|
406
|
-
const automergeIndex = space.automergeSpaceState.rootUrl;
|
|
407
|
-
invariant(automergeIndex);
|
|
408
|
-
const document = await this._echoHost.loadDoc<DatabaseDirectory>(Context.default(), automergeIndex as any, {
|
|
409
|
-
fetchFromNetwork: true,
|
|
410
|
-
});
|
|
411
|
-
await document.whenReady();
|
|
412
|
-
return document;
|
|
413
|
-
}
|
|
414
|
-
|
|
361
|
+
/**
|
|
362
|
+
* Accepts an existing space by joining its swarm and initializing the data pipeline.
|
|
363
|
+
* @param ctx - Caller context for cancellation and tracing.
|
|
364
|
+
* @param opts - Space keys and optional timeframes for catch-up.
|
|
365
|
+
*/
|
|
415
366
|
// TODO(burdon): Rename join space.
|
|
416
367
|
@synchronized
|
|
417
|
-
|
|
368
|
+
@trace.span({ showInBrowserTimeline: true, op: 'lifecycle' })
|
|
369
|
+
async acceptSpace(ctx: Context, opts: AcceptSpaceOptions): Promise<DataSpace> {
|
|
418
370
|
log('accept space', { opts });
|
|
419
371
|
invariant(this._lifecycleState === LifecycleState.OPEN, 'Not open.');
|
|
420
372
|
invariant(!this._spaces.has(opts.spaceKey), 'Space already exists.');
|
|
421
373
|
|
|
374
|
+
const tags = opts.tags ? Array.from(opts.tags) : [];
|
|
422
375
|
const metadata: SpaceMetadata = {
|
|
423
376
|
key: opts.spaceKey,
|
|
424
377
|
genesisFeedKey: opts.genesisFeedKey,
|
|
425
378
|
controlTimeframe: opts.controlTimeframe,
|
|
426
379
|
dataTimeframe: opts.dataTimeframe,
|
|
380
|
+
tags,
|
|
427
381
|
};
|
|
428
382
|
|
|
429
|
-
const space = await this._constructSpace(metadata);
|
|
430
|
-
await space.open();
|
|
383
|
+
const space = await this._constructSpace(ctx, metadata);
|
|
384
|
+
await space.open(ctx);
|
|
431
385
|
await this._metadataStore.addSpace(metadata);
|
|
432
|
-
|
|
386
|
+
// Use DSM lifecycle ctx: the invitation accept flow disposes `ctx` as soon as
|
|
387
|
+
// `acceptSpace` returns (guardedState.complete -> ctx.dispose). Detached data-pipeline
|
|
388
|
+
// initialization must outlive the invitation flow, and its span must be parented to a
|
|
389
|
+
// long-lived context.
|
|
390
|
+
space.initializeDataPipelineAsync(this._ctx);
|
|
433
391
|
|
|
434
392
|
this.updated.emit();
|
|
435
393
|
return space;
|
|
@@ -453,6 +411,7 @@ export class DataSpaceManager extends Resource {
|
|
|
453
411
|
space.spaceState.membershipChainHeads,
|
|
454
412
|
options.profile,
|
|
455
413
|
options.delegationCredentialId,
|
|
414
|
+
space.spaceState.tags,
|
|
456
415
|
);
|
|
457
416
|
|
|
458
417
|
// TODO(dmaretskyi): Refactor.
|
|
@@ -479,8 +438,8 @@ export class DataSpaceManager extends Resource {
|
|
|
479
438
|
);
|
|
480
439
|
}
|
|
481
440
|
|
|
482
|
-
public async requestSpaceAdmissionCredential(spaceKey: PublicKey): Promise<Credential> {
|
|
483
|
-
return this._spaceManager.requestSpaceAdmissionCredential({
|
|
441
|
+
public async requestSpaceAdmissionCredential(ctx: Context, spaceKey: PublicKey): Promise<Credential> {
|
|
442
|
+
return this._spaceManager.requestSpaceAdmissionCredential(ctx, {
|
|
484
443
|
spaceKey,
|
|
485
444
|
identityKey: this._signingContext.identityKey,
|
|
486
445
|
timeout: 15_000,
|
|
@@ -493,7 +452,11 @@ export class DataSpaceManager extends Resource {
|
|
|
493
452
|
});
|
|
494
453
|
}
|
|
495
454
|
|
|
496
|
-
async setSpaceEdgeReplicationSetting(
|
|
455
|
+
async setSpaceEdgeReplicationSetting(
|
|
456
|
+
ctx: Context,
|
|
457
|
+
spaceKey: PublicKey,
|
|
458
|
+
setting: EdgeReplicationSetting,
|
|
459
|
+
): Promise<void> {
|
|
497
460
|
const space = this._spaces.get(spaceKey);
|
|
498
461
|
invariant(space, 'Space not found.');
|
|
499
462
|
|
|
@@ -505,7 +468,7 @@ export class DataSpaceManager extends Resource {
|
|
|
505
468
|
await this._echoEdgeReplicator?.disconnectFromSpace(space.id);
|
|
506
469
|
break;
|
|
507
470
|
case EdgeReplicationSetting.ENABLED:
|
|
508
|
-
await this._echoEdgeReplicator?.connectToSpace(space.id);
|
|
471
|
+
await this._echoEdgeReplicator?.connectToSpace(ctx, space.id);
|
|
509
472
|
break;
|
|
510
473
|
}
|
|
511
474
|
}
|
|
@@ -513,7 +476,7 @@ export class DataSpaceManager extends Resource {
|
|
|
513
476
|
space.stateUpdate.emit();
|
|
514
477
|
}
|
|
515
478
|
|
|
516
|
-
private async _constructSpace(metadata: SpaceMetadata): Promise<DataSpace> {
|
|
479
|
+
private async _constructSpace(ctx: Context, metadata: SpaceMetadata): Promise<DataSpace> {
|
|
517
480
|
log('construct space', { metadata });
|
|
518
481
|
const gossip = new Gossip({
|
|
519
482
|
localPeerId: this._signingContext.deviceKey,
|
|
@@ -603,6 +566,7 @@ export class DataSpaceManager extends Resource {
|
|
|
603
566
|
},
|
|
604
567
|
},
|
|
605
568
|
cache: metadata.cache,
|
|
569
|
+
tags: metadata.tags,
|
|
606
570
|
edgeConnection: this._edgeConnection,
|
|
607
571
|
edgeHttpClient: this._edgeHttpClient,
|
|
608
572
|
edgeFeatures: this._edgeFeatures,
|
|
@@ -611,9 +575,10 @@ export class DataSpaceManager extends Resource {
|
|
|
611
575
|
dataSpace.postOpen.append(async () => {
|
|
612
576
|
const setting = dataSpace.getEdgeReplicationSetting();
|
|
613
577
|
if (!setting || setting === EdgeReplicationSetting.ENABLED) {
|
|
614
|
-
|
|
578
|
+
// Use lifecycle ctx: the caller ctx from _constructSpace may be disposed by the time postOpen fires.
|
|
579
|
+
await this._echoEdgeReplicator?.connectToSpace(this._ctx, dataSpace.id);
|
|
615
580
|
} else if (this._echoEdgeReplicator) {
|
|
616
|
-
log('not connecting
|
|
581
|
+
log('not connecting edge replicator because of EdgeReplicationSetting', { spaceId: dataSpace.id });
|
|
617
582
|
}
|
|
618
583
|
});
|
|
619
584
|
dataSpace.preClose.append(async () => {
|
|
@@ -708,7 +673,7 @@ export class DataSpaceManager extends Resource {
|
|
|
708
673
|
invitations: Array<[PublicKey, DelegateSpaceInvitation]>,
|
|
709
674
|
): Promise<void> {
|
|
710
675
|
const tasks = invitations.map(([credentialId, invitation]) => {
|
|
711
|
-
return this._invitationsManager.createInvitation({
|
|
676
|
+
return this._invitationsManager.createInvitation(this._ctx, {
|
|
712
677
|
type: Invitation.Type.DELEGATED,
|
|
713
678
|
kind: Invitation.Kind.SPACE,
|
|
714
679
|
spaceKey: space.key,
|