@dxos/client-services 0.5.9-main.bdf733d → 0.5.9-main.bf3bb8f
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-KNGR7BYM.mjs → chunk-IUSAD4RP.mjs} +1678 -935
- package/dist/lib/browser/chunk-IUSAD4RP.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +13 -4
- package/dist/lib/browser/index.mjs.map +1 -1
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/packlets/testing/index.mjs +20 -13
- package/dist/lib/browser/packlets/testing/index.mjs.map +3 -3
- package/dist/lib/node/{chunk-WWHTBQNR.cjs → chunk-5PALJZPW.cjs} +1936 -1200
- package/dist/lib/node/chunk-5PALJZPW.cjs.map +7 -0
- package/dist/lib/node/index.cjs +53 -44
- package/dist/lib/node/index.cjs.map +1 -1
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/packlets/testing/index.cjs +26 -19
- package/dist/lib/node/packlets/testing/index.cjs.map +3 -3
- package/dist/types/src/packlets/identity/contacts-service.d.ts +14 -0
- package/dist/types/src/packlets/identity/contacts-service.d.ts.map +1 -0
- package/dist/types/src/packlets/identity/default-space-state-machine.d.ts +19 -0
- package/dist/types/src/packlets/identity/default-space-state-machine.d.ts.map +1 -0
- package/dist/types/src/packlets/identity/identity-service.d.ts +14 -7
- package/dist/types/src/packlets/identity/identity-service.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity.d.ts +4 -1
- package/dist/types/src/packlets/identity/identity.d.ts.map +1 -1
- 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.map +1 -1
- package/dist/types/src/packlets/services/service-host.d.ts +1 -1
- package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/automerge-space-state.d.ts +4 -1
- 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 +15 -4
- package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/data-space.d.ts +10 -9
- package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/epoch-migrations.d.ts +23 -0
- package/dist/types/src/packlets/spaces/epoch-migrations.d.ts.map +1 -0
- package/dist/types/src/packlets/spaces/spaces-service.d.ts +5 -2
- package/dist/types/src/packlets/spaces/spaces-service.d.ts.map +1 -1
- package/dist/types/src/packlets/storage/index.d.ts +1 -0
- package/dist/types/src/packlets/storage/index.d.ts.map +1 -1
- package/dist/types/src/packlets/storage/profile-archive.d.ts +14 -0
- package/dist/types/src/packlets/storage/profile-archive.d.ts.map +1 -0
- package/dist/types/src/packlets/testing/test-builder.d.ts +8 -6
- package/dist/types/src/packlets/testing/test-builder.d.ts.map +1 -1
- package/dist/types/src/version.d.ts +1 -1
- package/package.json +36 -36
- package/src/packlets/identity/contacts-service.ts +85 -0
- package/src/packlets/identity/default-space-state-machine.ts +44 -0
- package/src/packlets/identity/identity-service.test.ts +35 -5
- package/src/packlets/identity/identity-service.ts +82 -8
- package/src/packlets/identity/identity.ts +25 -2
- package/src/packlets/invitations/invitations-handler.ts +13 -5
- package/src/packlets/invitations/space-invitation-protocol.ts +11 -32
- package/src/packlets/services/service-context.ts +1 -4
- package/src/packlets/services/service-host.ts +23 -42
- package/src/packlets/spaces/automerge-space-state.ts +11 -2
- package/src/packlets/spaces/data-space-manager.test.ts +46 -1
- package/src/packlets/spaces/data-space-manager.ts +136 -33
- package/src/packlets/spaces/data-space.ts +89 -140
- package/src/packlets/spaces/epoch-migrations.ts +154 -0
- package/src/packlets/spaces/spaces-service.ts +56 -4
- package/src/packlets/storage/index.ts +1 -0
- package/src/packlets/storage/profile-archive.ts +111 -0
- package/src/packlets/testing/test-builder.ts +12 -10
- package/src/version.ts +1 -1
- package/dist/lib/browser/chunk-KNGR7BYM.mjs.map +0 -7
- package/dist/lib/node/chunk-WWHTBQNR.cjs.map +0 -7
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import type { AutomergeUrl } from '@dxos/automerge/automerge-repo';
|
|
6
|
+
import { type Context } from '@dxos/context';
|
|
7
|
+
import {
|
|
8
|
+
convertLegacyReferences,
|
|
9
|
+
convertLegacySpaceRootDoc,
|
|
10
|
+
findInlineObjectOfType,
|
|
11
|
+
migrateDocument,
|
|
12
|
+
type EchoHost,
|
|
13
|
+
} from '@dxos/echo-db';
|
|
14
|
+
import { SpaceDocVersion, type SpaceDoc } from '@dxos/echo-protocol';
|
|
15
|
+
import { TYPE_PROPERTIES } from '@dxos/echo-schema';
|
|
16
|
+
import { invariant } from '@dxos/invariant';
|
|
17
|
+
import type { PublicKey, SpaceId } from '@dxos/keys';
|
|
18
|
+
import { log } from '@dxos/log';
|
|
19
|
+
import { CreateEpochRequest } from '@dxos/protocols/proto/dxos/client/services';
|
|
20
|
+
|
|
21
|
+
export type MigrationContext = {
|
|
22
|
+
echoHost: EchoHost;
|
|
23
|
+
|
|
24
|
+
spaceId: SpaceId;
|
|
25
|
+
/**
|
|
26
|
+
* @deprecated Remove.
|
|
27
|
+
*/
|
|
28
|
+
spaceKey: PublicKey;
|
|
29
|
+
migration: CreateEpochRequest.Migration;
|
|
30
|
+
currentRoot: string | null;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* For set automerge root migration type.
|
|
34
|
+
*/
|
|
35
|
+
newAutomergeRoot?: string;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export type MigrationResult = {
|
|
39
|
+
newRoot?: string;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const LOAD_DOC_TIMEOUT = 10_000;
|
|
43
|
+
|
|
44
|
+
export const runEpochMigration = async (ctx: Context, context: MigrationContext): Promise<MigrationResult> => {
|
|
45
|
+
switch (context.migration) {
|
|
46
|
+
case CreateEpochRequest.Migration.INIT_AUTOMERGE: {
|
|
47
|
+
const document = context.echoHost.createDoc();
|
|
48
|
+
await context.echoHost.flush();
|
|
49
|
+
return { newRoot: document.url };
|
|
50
|
+
}
|
|
51
|
+
case CreateEpochRequest.Migration.PRUNE_AUTOMERGE_ROOT_HISTORY: {
|
|
52
|
+
if (!context.currentRoot) {
|
|
53
|
+
throw new Error('Space does not have an automerge root');
|
|
54
|
+
}
|
|
55
|
+
const rootHandle = await context.echoHost.loadDoc(ctx, context.currentRoot as AutomergeUrl, {
|
|
56
|
+
timeout: LOAD_DOC_TIMEOUT,
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const newRoot = context.echoHost.createDoc(rootHandle.docSync());
|
|
60
|
+
await context.echoHost.flush();
|
|
61
|
+
return { newRoot: newRoot.url };
|
|
62
|
+
}
|
|
63
|
+
case CreateEpochRequest.Migration.FRAGMENT_AUTOMERGE_ROOT: {
|
|
64
|
+
log.info('Fragmenting');
|
|
65
|
+
|
|
66
|
+
const currentRootUrl = context.currentRoot;
|
|
67
|
+
const rootHandle = await context.echoHost.loadDoc<SpaceDoc>(ctx, currentRootUrl as any, {
|
|
68
|
+
timeout: LOAD_DOC_TIMEOUT,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Find properties object.
|
|
72
|
+
const objects = Object.entries((rootHandle.docSync() as SpaceDoc).objects!);
|
|
73
|
+
const properties = findInlineObjectOfType(rootHandle.docSync() as SpaceDoc, TYPE_PROPERTIES);
|
|
74
|
+
const otherObjects = objects.filter(([key]) => key !== properties?.[0]);
|
|
75
|
+
invariant(properties, 'Properties not found');
|
|
76
|
+
|
|
77
|
+
// Create a new space doc with the properties object.
|
|
78
|
+
const newRoot = context.echoHost.createDoc({
|
|
79
|
+
...rootHandle.docSync(),
|
|
80
|
+
objects: Object.fromEntries([properties]),
|
|
81
|
+
});
|
|
82
|
+
invariant(typeof newRoot.url === 'string' && newRoot.url.length > 0);
|
|
83
|
+
|
|
84
|
+
// Create new automerge documents for all objects.
|
|
85
|
+
const newLinks: [string, AutomergeUrl][] = [];
|
|
86
|
+
for (const [id, objData] of otherObjects) {
|
|
87
|
+
const handle = context.echoHost.createDoc<SpaceDoc>({
|
|
88
|
+
version: SpaceDocVersion.CURRENT,
|
|
89
|
+
access: {
|
|
90
|
+
spaceKey: context.spaceKey.toHex(),
|
|
91
|
+
},
|
|
92
|
+
objects: {
|
|
93
|
+
[id]: objData,
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
newLinks.push([id, handle.url]);
|
|
97
|
+
}
|
|
98
|
+
newRoot.change((doc: SpaceDoc) => {
|
|
99
|
+
doc.links ??= {};
|
|
100
|
+
for (const [id, url] of newLinks) {
|
|
101
|
+
doc.links[id] = url;
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
await context.echoHost.flush();
|
|
106
|
+
return {
|
|
107
|
+
newRoot: newRoot.url,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
case CreateEpochRequest.Migration.MIGRATE_REFERENCES_TO_DXN: {
|
|
111
|
+
const currentRootUrl = context.currentRoot;
|
|
112
|
+
const rootHandle = await context.echoHost.loadDoc<SpaceDoc>(ctx, currentRootUrl as any, {
|
|
113
|
+
timeout: LOAD_DOC_TIMEOUT,
|
|
114
|
+
});
|
|
115
|
+
invariant(rootHandle.docSync(), 'Root doc not found');
|
|
116
|
+
|
|
117
|
+
const newRootContent = await convertLegacySpaceRootDoc(structuredClone(rootHandle.docSync()!));
|
|
118
|
+
|
|
119
|
+
for (const [id, url] of Object.entries(newRootContent.links ?? {})) {
|
|
120
|
+
try {
|
|
121
|
+
const handle = await context.echoHost.loadDoc(ctx, url as any, { timeout: LOAD_DOC_TIMEOUT });
|
|
122
|
+
invariant(handle.docSync());
|
|
123
|
+
const newDoc = await convertLegacyReferences(structuredClone(handle.docSync()!));
|
|
124
|
+
const migratedDoc = migrateDocument(handle.docSync(), newDoc);
|
|
125
|
+
const newHandle = context.echoHost.createDoc(migratedDoc, { preserveHistory: true });
|
|
126
|
+
newRootContent.links![id] = newHandle.url;
|
|
127
|
+
} catch (err) {
|
|
128
|
+
log.warn('Failed to migrate reference', { id, url, error: err });
|
|
129
|
+
delete newRootContent.links![id];
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const migratedRoot = migrateDocument(rootHandle.docSync(), newRootContent);
|
|
134
|
+
const newRoot = context.echoHost.createDoc(migratedRoot, { preserveHistory: true });
|
|
135
|
+
|
|
136
|
+
await context.echoHost.flush();
|
|
137
|
+
return {
|
|
138
|
+
newRoot: newRoot.url,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
// TODO(dmaretskyi): This path doesn't seem to fit here. This is not a migration.
|
|
142
|
+
case CreateEpochRequest.Migration.REPLACE_AUTOMERGE_ROOT: {
|
|
143
|
+
invariant(context.newAutomergeRoot);
|
|
144
|
+
|
|
145
|
+
// Defensive programming - it should be the responsibility of the caller to flush the new root.
|
|
146
|
+
await context.echoHost.flush();
|
|
147
|
+
return {
|
|
148
|
+
newRoot: context.newAutomergeRoot,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return {};
|
|
154
|
+
};
|
|
@@ -30,6 +30,11 @@ import {
|
|
|
30
30
|
type UpdateSpaceRequest,
|
|
31
31
|
type WriteCredentialsRequest,
|
|
32
32
|
type UpdateMemberRoleRequest,
|
|
33
|
+
type AdmitContactRequest,
|
|
34
|
+
type ContactAdmission,
|
|
35
|
+
type JoinSpaceResponse,
|
|
36
|
+
type JoinBySpaceKeyRequest,
|
|
37
|
+
type CreateEpochResponse,
|
|
33
38
|
} from '@dxos/protocols/proto/dxos/client/services';
|
|
34
39
|
import { type Credential } from '@dxos/protocols/proto/dxos/halo/credentials';
|
|
35
40
|
import { type GossipMessage } from '@dxos/protocols/proto/dxos/mesh/teleport/gossip';
|
|
@@ -125,8 +130,18 @@ export class SpacesServiceImpl implements SpacesService {
|
|
|
125
130
|
subscriptions.clear();
|
|
126
131
|
|
|
127
132
|
for (const space of dataSpaceManager.spaces.values()) {
|
|
128
|
-
|
|
129
|
-
subscriptions.add(
|
|
133
|
+
let lastState: SpaceState | undefined;
|
|
134
|
+
subscriptions.add(
|
|
135
|
+
space.stateUpdate.on(ctx, () => {
|
|
136
|
+
// Always send a separate update if the space state has changed.
|
|
137
|
+
if (space.state !== lastState) {
|
|
138
|
+
scheduler.forceTrigger();
|
|
139
|
+
} else {
|
|
140
|
+
scheduler.trigger();
|
|
141
|
+
}
|
|
142
|
+
lastState = space.state;
|
|
143
|
+
}),
|
|
144
|
+
);
|
|
130
145
|
|
|
131
146
|
subscriptions.add(space.presence.updated.on(ctx, () => scheduler.trigger()));
|
|
132
147
|
subscriptions.add(space.automergeSpaceState.onNewEpoch.on(ctx, () => scheduler.trigger()));
|
|
@@ -208,10 +223,45 @@ export class SpacesServiceImpl implements SpacesService {
|
|
|
208
223
|
}
|
|
209
224
|
}
|
|
210
225
|
|
|
211
|
-
async createEpoch({ spaceKey, migration }: CreateEpochRequest) {
|
|
226
|
+
async createEpoch({ spaceKey, migration, automergeRootUrl }: CreateEpochRequest): Promise<CreateEpochResponse> {
|
|
212
227
|
const dataSpaceManager = await this._getDataSpaceManager();
|
|
213
228
|
const space = dataSpaceManager.spaces.get(spaceKey) ?? raise(new SpaceNotFoundError(spaceKey));
|
|
214
|
-
await space.createEpoch({ migration });
|
|
229
|
+
const credential = await space.createEpoch({ migration, newAutomergeRoot: automergeRootUrl });
|
|
230
|
+
return { epochCredential: credential ?? undefined };
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
async admitContact(request: AdmitContactRequest): Promise<void> {
|
|
234
|
+
const dataSpaceManager = await this._getDataSpaceManager();
|
|
235
|
+
await dataSpaceManager.admitMember({
|
|
236
|
+
spaceKey: request.spaceKey,
|
|
237
|
+
identityKey: request.contact.identityKey,
|
|
238
|
+
role: request.role,
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
async joinBySpaceKey({ spaceKey }: JoinBySpaceKeyRequest): Promise<JoinSpaceResponse> {
|
|
243
|
+
const dataSpaceManager = await this._getDataSpaceManager();
|
|
244
|
+
const credential = await dataSpaceManager.requestSpaceAdmissionCredential(spaceKey);
|
|
245
|
+
return this._joinByAdmission({ credential });
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
private async _joinByAdmission({ credential }: ContactAdmission): Promise<JoinSpaceResponse> {
|
|
249
|
+
const assertion = getCredentialAssertion(credential);
|
|
250
|
+
invariant(assertion['@type'] === 'dxos.halo.credentials.SpaceMember', 'Invalid credential');
|
|
251
|
+
const myIdentity = this._identityManager.identity;
|
|
252
|
+
invariant(myIdentity && credential.subject.id.equals(myIdentity.identityKey));
|
|
253
|
+
|
|
254
|
+
const dataSpaceManager = await this._getDataSpaceManager();
|
|
255
|
+
let dataSpace = dataSpaceManager.spaces.get(assertion.spaceKey);
|
|
256
|
+
if (!dataSpace) {
|
|
257
|
+
dataSpace = await dataSpaceManager.acceptSpace({
|
|
258
|
+
spaceKey: assertion.spaceKey,
|
|
259
|
+
genesisFeedKey: assertion.genesisFeedKey,
|
|
260
|
+
});
|
|
261
|
+
await myIdentity.controlPipeline.writer.write({ credential: { credential } });
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return { space: this._serializeSpace(dataSpace) };
|
|
215
265
|
}
|
|
216
266
|
|
|
217
267
|
private _serializeSpace(space: DataSpace): Space {
|
|
@@ -234,6 +284,8 @@ export class SpacesServiceImpl implements SpacesService {
|
|
|
234
284
|
currentDataTimeframe: undefined,
|
|
235
285
|
targetDataTimeframe: undefined,
|
|
236
286
|
totalDataTimeframe: undefined,
|
|
287
|
+
|
|
288
|
+
spaceRootUrl: space.databaseRoot?.url,
|
|
237
289
|
},
|
|
238
290
|
members: Array.from(space.inner.spaceState.members.values()).map((member) => {
|
|
239
291
|
const peers = space.presence.getPeersOnline().filter(({ identityKey }) => identityKey.equals(member.key));
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { cbor } from '@dxos/automerge/automerge-repo';
|
|
6
|
+
import { invariant } from '@dxos/invariant';
|
|
7
|
+
import type { LevelDB } from '@dxos/kv-store';
|
|
8
|
+
import { log } from '@dxos/log';
|
|
9
|
+
import { ProfileArchiveEntryType, type ProfileArchive } from '@dxos/protocols';
|
|
10
|
+
import type { Storage } from '@dxos/random-access-storage';
|
|
11
|
+
import { arrayToBuffer } from '@dxos/util';
|
|
12
|
+
|
|
13
|
+
export const encodeProfileArchive = (profile: ProfileArchive): Uint8Array => cbor.encode(profile);
|
|
14
|
+
|
|
15
|
+
export const decodeProfileArchive = (data: Uint8Array): ProfileArchive => cbor.decode(data);
|
|
16
|
+
|
|
17
|
+
export const exportProfileData = async ({
|
|
18
|
+
storage,
|
|
19
|
+
level,
|
|
20
|
+
}: {
|
|
21
|
+
storage: Storage;
|
|
22
|
+
level: LevelDB;
|
|
23
|
+
}): Promise<ProfileArchive> => {
|
|
24
|
+
const archive: ProfileArchive = { storage: [], meta: { timestamp: new Date().toISOString() } };
|
|
25
|
+
|
|
26
|
+
{
|
|
27
|
+
const directory = await storage.createDirectory();
|
|
28
|
+
const files = await directory.list();
|
|
29
|
+
|
|
30
|
+
log.info('begin exporting files', { count: files.length });
|
|
31
|
+
for (const filename of files) {
|
|
32
|
+
const file = await directory.getOrCreateFile(filename);
|
|
33
|
+
const { size } = await file.stat();
|
|
34
|
+
const data = await file.read(0, size);
|
|
35
|
+
archive.storage.push({
|
|
36
|
+
type: ProfileArchiveEntryType.FILE,
|
|
37
|
+
key: filename,
|
|
38
|
+
value: data,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
log.info('done exporting files', { count: files.length });
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
{
|
|
45
|
+
log.info('begin exporting kv pairs');
|
|
46
|
+
const iter = await level.iterator<Uint8Array, Uint8Array>({ keyEncoding: 'binary', valueEncoding: 'binary' });
|
|
47
|
+
let count = 0;
|
|
48
|
+
for await (const [key, value] of iter) {
|
|
49
|
+
archive.storage.push({
|
|
50
|
+
type: ProfileArchiveEntryType.KEY_VALUE,
|
|
51
|
+
key,
|
|
52
|
+
value,
|
|
53
|
+
});
|
|
54
|
+
count++;
|
|
55
|
+
}
|
|
56
|
+
log.info('done exporting kv pairs', { count });
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return archive;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export const importProfileData = async (
|
|
63
|
+
{
|
|
64
|
+
storage,
|
|
65
|
+
level,
|
|
66
|
+
}: {
|
|
67
|
+
storage: Storage;
|
|
68
|
+
level: LevelDB;
|
|
69
|
+
},
|
|
70
|
+
archive: ProfileArchive,
|
|
71
|
+
): Promise<void> => {
|
|
72
|
+
let batch = level.batch();
|
|
73
|
+
|
|
74
|
+
let count = 0;
|
|
75
|
+
for (const entry of archive.storage) {
|
|
76
|
+
switch (entry.type) {
|
|
77
|
+
case ProfileArchiveEntryType.FILE: {
|
|
78
|
+
const directory = await storage.createDirectory();
|
|
79
|
+
invariant(typeof entry.key === 'string', 'Invalid key type');
|
|
80
|
+
const file = await directory.getOrCreateFile(entry.key);
|
|
81
|
+
invariant(entry.value instanceof Uint8Array, 'Invalid value type');
|
|
82
|
+
await file.write(0, arrayToBuffer(entry.value));
|
|
83
|
+
await file.close();
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
case ProfileArchiveEntryType.KEY_VALUE: {
|
|
87
|
+
invariant(entry.key instanceof Uint8Array, 'Invalid key type');
|
|
88
|
+
invariant(entry.value instanceof Uint8Array, 'Invalid value type');
|
|
89
|
+
batch.put(entry.key, entry.value, { keyEncoding: 'binary', valueEncoding: 'binary' });
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
default:
|
|
93
|
+
throw new Error(`Invalid entry type: ${entry.type}`);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (++count % 1000 === 0) {
|
|
97
|
+
// Apparently indexedDB can't handle big batches.
|
|
98
|
+
await batch.write();
|
|
99
|
+
batch = level.batch();
|
|
100
|
+
|
|
101
|
+
log.info('importing', {
|
|
102
|
+
count,
|
|
103
|
+
total: archive.storage.length,
|
|
104
|
+
progress: `${((count / archive.storage.length) * 100).toFixed()}%`,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
log.info('committing changes..');
|
|
110
|
+
await batch.write();
|
|
111
|
+
};
|
|
@@ -19,8 +19,8 @@ import { createStorage, StorageType, type Storage } from '@dxos/random-access-st
|
|
|
19
19
|
import { BlobStore } from '@dxos/teleport-extension-object-sync';
|
|
20
20
|
|
|
21
21
|
import { InvitationsHandler, InvitationsManager, SpaceInvitationProtocol } from '../invitations';
|
|
22
|
-
import { ClientServicesHost, ServiceContext } from '../services';
|
|
23
|
-
import { DataSpaceManager, type SigningContext } from '../spaces';
|
|
22
|
+
import { ClientServicesHost, ServiceContext, type ServiceContextRuntimeParams } from '../services';
|
|
23
|
+
import { DataSpaceManager, type DataSpaceManagerRuntimeParams, type SigningContext } from '../spaces';
|
|
24
24
|
|
|
25
25
|
//
|
|
26
26
|
// TODO(burdon): Replace with test builder.
|
|
@@ -37,9 +37,11 @@ export const createServiceHost = (config: Config, signalManagerContext: MemorySi
|
|
|
37
37
|
export const createServiceContext = async ({
|
|
38
38
|
signalContext = new MemorySignalManagerContext(),
|
|
39
39
|
storage = createStorage({ type: StorageType.RAM }),
|
|
40
|
+
runtimeParams,
|
|
40
41
|
}: {
|
|
41
42
|
signalContext?: MemorySignalManagerContext;
|
|
42
43
|
storage?: Storage;
|
|
44
|
+
runtimeParams?: ServiceContextRuntimeParams;
|
|
43
45
|
} = {}) => {
|
|
44
46
|
const signalManager = new MemorySignalManager(signalContext);
|
|
45
47
|
const networkManager = new SwarmNetworkManager({
|
|
@@ -51,6 +53,7 @@ export const createServiceContext = async ({
|
|
|
51
53
|
|
|
52
54
|
return new ServiceContext(storage, level, networkManager, signalManager, {
|
|
53
55
|
invitationConnectionDefaultParams: { controlHeartbeatInterval: 200 },
|
|
56
|
+
...runtimeParams,
|
|
54
57
|
});
|
|
55
58
|
};
|
|
56
59
|
|
|
@@ -88,6 +91,7 @@ export class TestBuilder {
|
|
|
88
91
|
|
|
89
92
|
export type TestPeerOpts = {
|
|
90
93
|
dataStore?: StorageType;
|
|
94
|
+
dataSpaceParams?: DataSpaceManagerRuntimeParams;
|
|
91
95
|
};
|
|
92
96
|
|
|
93
97
|
export type TestPeerProps = {
|
|
@@ -110,8 +114,8 @@ export class TestPeer {
|
|
|
110
114
|
private _props: TestPeerProps = {};
|
|
111
115
|
|
|
112
116
|
constructor(
|
|
113
|
-
private readonly
|
|
114
|
-
private readonly
|
|
117
|
+
private readonly _signalContext: MemorySignalManagerContext,
|
|
118
|
+
private readonly _opts: TestPeerOpts = { dataStore: StorageType.RAM },
|
|
115
119
|
) {}
|
|
116
120
|
|
|
117
121
|
get props() {
|
|
@@ -119,7 +123,7 @@ export class TestPeer {
|
|
|
119
123
|
}
|
|
120
124
|
|
|
121
125
|
get storage() {
|
|
122
|
-
return (this._props.storage ??= createStorage({ type: this.
|
|
126
|
+
return (this._props.storage ??= createStorage({ type: this._opts.dataStore }));
|
|
123
127
|
}
|
|
124
128
|
|
|
125
129
|
get keyring() {
|
|
@@ -156,7 +160,7 @@ export class TestPeer {
|
|
|
156
160
|
|
|
157
161
|
get networkManager() {
|
|
158
162
|
return (this._props.networkManager ??= new SwarmNetworkManager({
|
|
159
|
-
signalManager: new MemorySignalManager(this.
|
|
163
|
+
signalManager: new MemorySignalManager(this._signalContext),
|
|
160
164
|
transportFactory: MemoryTransportFactory,
|
|
161
165
|
}));
|
|
162
166
|
}
|
|
@@ -176,10 +180,7 @@ export class TestPeer {
|
|
|
176
180
|
}
|
|
177
181
|
|
|
178
182
|
get echoHost() {
|
|
179
|
-
return (this._props.echoHost ??= new EchoHost({
|
|
180
|
-
kv: this.level,
|
|
181
|
-
storage: this.storage,
|
|
182
|
-
}));
|
|
183
|
+
return (this._props.echoHost ??= new EchoHost({ kv: this.level }));
|
|
183
184
|
}
|
|
184
185
|
|
|
185
186
|
get dataSpaceManager(): DataSpaceManager {
|
|
@@ -191,6 +192,7 @@ export class TestPeer {
|
|
|
191
192
|
this.feedStore,
|
|
192
193
|
this.echoHost,
|
|
193
194
|
this.invitationsManager,
|
|
195
|
+
this._opts.dataSpaceParams,
|
|
194
196
|
));
|
|
195
197
|
}
|
|
196
198
|
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const DXOS_VERSION = "0.5.9-main.
|
|
1
|
+
export const DXOS_VERSION = "0.5.9-main.bf3bb8f";
|