@dxos/client-services 0.5.9-main.cb71230 → 0.5.9-main.d63ef8d

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/dist/lib/browser/{chunk-HSM5JUN6.mjs → chunk-C2VXW65X.mjs} +1101 -805
  2. package/dist/lib/browser/chunk-C2VXW65X.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +1 -3
  4. package/dist/lib/browser/index.mjs.map +1 -1
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/packlets/testing/index.mjs +11 -11
  7. package/dist/lib/browser/packlets/testing/index.mjs.map +3 -3
  8. package/dist/lib/node/{chunk-4OGPGXOU.cjs → chunk-OD7BTUYY.cjs} +1399 -1110
  9. package/dist/lib/node/chunk-OD7BTUYY.cjs.map +7 -0
  10. package/dist/lib/node/index.cjs +41 -43
  11. package/dist/lib/node/index.cjs.map +1 -1
  12. package/dist/lib/node/meta.json +1 -1
  13. package/dist/lib/node/packlets/testing/index.cjs +17 -17
  14. package/dist/lib/node/packlets/testing/index.cjs.map +3 -3
  15. package/dist/types/src/packlets/identity/default-space-state-machine.d.ts +19 -0
  16. package/dist/types/src/packlets/identity/default-space-state-machine.d.ts.map +1 -0
  17. package/dist/types/src/packlets/identity/identity-service.d.ts +14 -7
  18. package/dist/types/src/packlets/identity/identity-service.d.ts.map +1 -1
  19. package/dist/types/src/packlets/identity/identity.d.ts +4 -1
  20. package/dist/types/src/packlets/identity/identity.d.ts.map +1 -1
  21. package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
  22. package/dist/types/src/packlets/services/service-host.d.ts +1 -1
  23. package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
  24. package/dist/types/src/packlets/spaces/automerge-space-state.d.ts +4 -1
  25. package/dist/types/src/packlets/spaces/automerge-space-state.d.ts.map +1 -1
  26. package/dist/types/src/packlets/spaces/data-space-manager.d.ts +5 -3
  27. package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
  28. package/dist/types/src/packlets/spaces/data-space.d.ts +9 -9
  29. package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
  30. package/dist/types/src/packlets/spaces/epoch-migrations.d.ts +23 -0
  31. package/dist/types/src/packlets/spaces/epoch-migrations.d.ts.map +1 -0
  32. package/dist/types/src/packlets/spaces/spaces-service.d.ts +2 -2
  33. package/dist/types/src/packlets/spaces/spaces-service.d.ts.map +1 -1
  34. package/dist/types/src/packlets/testing/test-builder.d.ts +8 -6
  35. package/dist/types/src/packlets/testing/test-builder.d.ts.map +1 -1
  36. package/dist/types/src/version.d.ts +1 -1
  37. package/package.json +36 -36
  38. package/src/packlets/identity/default-space-state-machine.ts +44 -0
  39. package/src/packlets/identity/identity-service.test.ts +35 -5
  40. package/src/packlets/identity/identity-service.ts +76 -8
  41. package/src/packlets/identity/identity.ts +25 -2
  42. package/src/packlets/services/service-context.ts +1 -4
  43. package/src/packlets/services/service-host.ts +13 -40
  44. package/src/packlets/spaces/automerge-space-state.ts +11 -2
  45. package/src/packlets/spaces/data-space-manager.test.ts +46 -1
  46. package/src/packlets/spaces/data-space-manager.ts +81 -31
  47. package/src/packlets/spaces/data-space.ts +82 -149
  48. package/src/packlets/spaces/epoch-migrations.ts +135 -0
  49. package/src/packlets/spaces/spaces-service.ts +4 -2
  50. package/src/packlets/testing/test-builder.ts +12 -10
  51. package/src/version.ts +1 -1
  52. package/dist/lib/browser/chunk-HSM5JUN6.mjs.map +0 -7
  53. package/dist/lib/node/chunk-4OGPGXOU.cjs.map +0 -7
@@ -0,0 +1,135 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { asyncTimeout } from '@dxos/async';
6
+ import { next as am } from '@dxos/automerge/automerge';
7
+ import type { Repo, AutomergeUrl } from '@dxos/automerge/automerge-repo';
8
+ import { cancelWithContext, type Context } from '@dxos/context';
9
+ import {
10
+ convertLegacyReferences,
11
+ convertLegacySpaceRootDoc,
12
+ findInlineObjectOfType,
13
+ migrateDocument,
14
+ } from '@dxos/echo-db';
15
+ import { AutomergeDocumentLoaderImpl } from '@dxos/echo-pipeline';
16
+ import type { SpaceDoc } from '@dxos/echo-protocol';
17
+ import { TYPE_PROPERTIES } from '@dxos/echo-schema';
18
+ import { invariant } from '@dxos/invariant';
19
+ import type { PublicKey, SpaceId } from '@dxos/keys';
20
+ import { log } from '@dxos/log';
21
+ import { CreateEpochRequest } from '@dxos/protocols/proto/dxos/client/services';
22
+ import { assignDeep } from '@dxos/util';
23
+
24
+ export type MigrationContext = {
25
+ repo: Repo;
26
+ spaceId: SpaceId;
27
+ /**
28
+ * @deprecated Remove.
29
+ */
30
+ spaceKey: PublicKey;
31
+ migration: CreateEpochRequest.Migration;
32
+ currentRoot: string | null;
33
+
34
+ /**
35
+ * For set automerge root migration type.
36
+ */
37
+ newAutomergeRoot?: string;
38
+ };
39
+
40
+ export type MigrationResult = {
41
+ newRoot?: string;
42
+ };
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.repo.create();
48
+ await context.repo.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 = context.repo.find(context.currentRoot as AutomergeUrl);
56
+ await cancelWithContext(ctx, asyncTimeout(rootHandle.whenReady(), 10_000));
57
+
58
+ const newRoot = context.repo.create(rootHandle.docSync());
59
+ await context.repo.flush();
60
+ return { newRoot: newRoot.url };
61
+ }
62
+ case CreateEpochRequest.Migration.FRAGMENT_AUTOMERGE_ROOT: {
63
+ log.info('Fragmenting');
64
+
65
+ const currentRootUrl = context.currentRoot;
66
+ const rootHandle = context.repo.find<SpaceDoc>(currentRootUrl as any);
67
+ await cancelWithContext(ctx, asyncTimeout(rootHandle.whenReady(), 10_000));
68
+
69
+ // Find properties object.
70
+ const objects = Object.entries((rootHandle.docSync() as SpaceDoc).objects!);
71
+ const properties = findInlineObjectOfType(rootHandle.docSync() as SpaceDoc, TYPE_PROPERTIES);
72
+ const otherObjects = objects.filter(([key]) => key !== properties?.[0]);
73
+ invariant(properties, 'Properties not found');
74
+
75
+ // Create a new space doc with the properties object.
76
+ const newSpaceDoc: SpaceDoc = { ...rootHandle.docSync(), objects: Object.fromEntries([properties]) };
77
+ const newRoot = context.repo.create(newSpaceDoc);
78
+ invariant(typeof newRoot.url === 'string' && newRoot.url.length > 0);
79
+
80
+ // Create new automerge documents for all objects.
81
+ const docLoader = new AutomergeDocumentLoaderImpl(context.spaceId, context.repo, context.spaceKey);
82
+ await docLoader.loadSpaceRootDocHandle(ctx, { rootUrl: newRoot.url });
83
+
84
+ otherObjects.forEach(([key, value]) => {
85
+ const handle = docLoader.createDocumentForObject(key);
86
+ handle.change((doc: any) => {
87
+ assignDeep(doc, ['objects', key], value);
88
+ });
89
+ });
90
+
91
+ await context.repo.flush();
92
+ return {
93
+ newRoot: newRoot.url,
94
+ };
95
+ }
96
+ case CreateEpochRequest.Migration.MIGRATE_REFERENCES_TO_DXN: {
97
+ const currentRootUrl = context.currentRoot;
98
+ const rootHandle = context.repo.find<SpaceDoc>(currentRootUrl as any);
99
+ await cancelWithContext(ctx, asyncTimeout(rootHandle.whenReady(), 10_000));
100
+ invariant(rootHandle.docSync(), 'Root doc not found');
101
+
102
+ const newRootContent = await convertLegacySpaceRootDoc(structuredClone(rootHandle.docSync()!));
103
+
104
+ for (const [id, url] of Object.entries(newRootContent.links ?? {})) {
105
+ const handle = context.repo.find(url as any);
106
+ await cancelWithContext(ctx, asyncTimeout(handle.whenReady(), 10_000));
107
+ invariant(handle.docSync(), 'Doc not found');
108
+ const newDoc = await convertLegacyReferences(structuredClone(handle.docSync()!));
109
+ const migratedDoc = migrateDocument(handle.docSync(), newDoc);
110
+ const newHandle = context.repo.import(am.save(migratedDoc));
111
+ newRootContent.links![id] = newHandle.url;
112
+ }
113
+
114
+ const migratedRoot = migrateDocument(rootHandle.docSync(), newRootContent);
115
+ const newRoot = context.repo.import(am.save(migratedRoot));
116
+
117
+ await context.repo.flush();
118
+ return {
119
+ newRoot: newRoot.url,
120
+ };
121
+ }
122
+ // TODO(dmaretskyi): This path doesn't seem to fit here. This is not a migration.
123
+ case CreateEpochRequest.Migration.REPLACE_AUTOMERGE_ROOT: {
124
+ invariant(context.newAutomergeRoot);
125
+
126
+ // Defensive programming - it should be the responsibility of the caller to flush the new root.
127
+ await context.repo.flush();
128
+ return {
129
+ newRoot: context.newAutomergeRoot,
130
+ };
131
+ }
132
+ }
133
+
134
+ return {};
135
+ };
@@ -30,6 +30,7 @@ import {
30
30
  type UpdateSpaceRequest,
31
31
  type WriteCredentialsRequest,
32
32
  type UpdateMemberRoleRequest,
33
+ type CreateEpochResponse,
33
34
  } from '@dxos/protocols/proto/dxos/client/services';
34
35
  import { type Credential } from '@dxos/protocols/proto/dxos/halo/credentials';
35
36
  import { type GossipMessage } from '@dxos/protocols/proto/dxos/mesh/teleport/gossip';
@@ -208,10 +209,11 @@ export class SpacesServiceImpl implements SpacesService {
208
209
  }
209
210
  }
210
211
 
211
- async createEpoch({ spaceKey, migration, automergeRootUrl }: CreateEpochRequest) {
212
+ async createEpoch({ spaceKey, migration, automergeRootUrl }: CreateEpochRequest): Promise<CreateEpochResponse> {
212
213
  const dataSpaceManager = await this._getDataSpaceManager();
213
214
  const space = dataSpaceManager.spaces.get(spaceKey) ?? raise(new SpaceNotFoundError(spaceKey));
214
- await space.createEpoch({ migration, newAutomergeRoot: automergeRootUrl });
215
+ const credential = await space.createEpoch({ migration, newAutomergeRoot: automergeRootUrl });
216
+ return { epochCredential: credential ?? undefined };
215
217
  }
216
218
 
217
219
  private _serializeSpace(space: DataSpace): Space {
@@ -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 signalContext: MemorySignalManagerContext,
114
- private readonly opts: TestPeerOpts = { dataStore: StorageType.RAM },
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.opts.dataStore }));
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.signalContext),
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.cb71230";
1
+ export const DXOS_VERSION = "0.5.9-main.d63ef8d";