@dxos/client-services 0.5.0 → 0.5.1-main.0ec204c

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 (95) hide show
  1. package/dist/lib/browser/{chunk-ESEYLOPB.mjs → chunk-5I77NB7R.mjs} +1437 -1119
  2. package/dist/lib/browser/chunk-5I77NB7R.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +36 -5
  4. package/dist/lib/browser/index.mjs.map +3 -3
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/packlets/testing/index.mjs +36 -14
  7. package/dist/lib/browser/packlets/testing/index.mjs.map +3 -3
  8. package/dist/lib/node/{chunk-GA7JFIXK.cjs → chunk-W24O4MIS.cjs} +1552 -1238
  9. package/dist/lib/node/chunk-W24O4MIS.cjs.map +7 -0
  10. package/dist/lib/node/index.cjs +78 -47
  11. package/dist/lib/node/index.cjs.map +3 -3
  12. package/dist/lib/node/meta.json +1 -1
  13. package/dist/lib/node/packlets/testing/index.cjs +40 -18
  14. package/dist/lib/node/packlets/testing/index.cjs.map +3 -3
  15. package/dist/types/src/packlets/diagnostics/diagnostics-collector.d.ts.map +1 -1
  16. package/dist/types/src/packlets/diagnostics/diagnostics.d.ts.map +1 -1
  17. package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts +2 -1
  18. package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts.map +1 -1
  19. package/dist/types/src/packlets/invitations/invitation-guest-extenstion.d.ts +39 -0
  20. package/dist/types/src/packlets/invitations/invitation-guest-extenstion.d.ts.map +1 -0
  21. package/dist/types/src/packlets/invitations/{invitation-extension.d.ts → invitation-host-extension.d.ts} +17 -31
  22. package/dist/types/src/packlets/invitations/invitation-host-extension.d.ts.map +1 -0
  23. package/dist/types/src/packlets/invitations/invitation-protocol.d.ts +6 -1
  24. package/dist/types/src/packlets/invitations/invitation-protocol.d.ts.map +1 -1
  25. package/dist/types/src/packlets/invitations/invitation-topology.d.ts +37 -0
  26. package/dist/types/src/packlets/invitations/invitation-topology.d.ts.map +1 -0
  27. package/dist/types/src/packlets/invitations/invitations-handler.d.ts +19 -10
  28. package/dist/types/src/packlets/invitations/invitations-handler.d.ts.map +1 -1
  29. package/dist/types/src/packlets/invitations/invitations-handler.test.d.ts +2 -0
  30. package/dist/types/src/packlets/invitations/invitations-handler.test.d.ts.map +1 -0
  31. package/dist/types/src/packlets/invitations/invitations-manager.d.ts +2 -1
  32. package/dist/types/src/packlets/invitations/invitations-manager.d.ts.map +1 -1
  33. package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts +1 -0
  34. package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts.map +1 -1
  35. package/dist/types/src/packlets/invitations/utils.d.ts +6 -0
  36. package/dist/types/src/packlets/invitations/utils.d.ts.map +1 -0
  37. package/dist/types/src/packlets/services/service-context.d.ts +12 -11
  38. package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
  39. package/dist/types/src/packlets/services/service-host.d.ts +1 -2
  40. package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
  41. package/dist/types/src/packlets/spaces/data-space-manager.d.ts +4 -3
  42. package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
  43. package/dist/types/src/packlets/spaces/data-space.d.ts +4 -3
  44. package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
  45. package/dist/types/src/packlets/spaces/spaces-service.d.ts +2 -1
  46. package/dist/types/src/packlets/spaces/spaces-service.d.ts.map +1 -1
  47. package/dist/types/src/packlets/storage/level.d.ts +1 -2
  48. package/dist/types/src/packlets/storage/level.d.ts.map +1 -1
  49. package/dist/types/src/packlets/testing/invitation-utils.d.ts +2 -1
  50. package/dist/types/src/packlets/testing/invitation-utils.d.ts.map +1 -1
  51. package/dist/types/src/packlets/testing/test-builder.d.ts +5 -3
  52. package/dist/types/src/packlets/testing/test-builder.d.ts.map +1 -1
  53. package/dist/types/src/packlets/vault/shell-runtime.d.ts +10 -2
  54. package/dist/types/src/packlets/vault/shell-runtime.d.ts.map +1 -1
  55. package/dist/types/src/packlets/vault/worker-runtime.d.ts.map +1 -1
  56. package/dist/types/src/version.d.ts +1 -1
  57. package/dist/types/src/version.d.ts.map +1 -1
  58. package/package.json +36 -35
  59. package/src/packlets/diagnostics/diagnostics-collector.ts +14 -9
  60. package/src/packlets/diagnostics/diagnostics.ts +78 -68
  61. package/src/packlets/invitations/device-invitation-protocol.ts +5 -1
  62. package/src/packlets/invitations/invitation-guest-extenstion.ts +126 -0
  63. package/src/packlets/invitations/{invitation-extension.ts → invitation-host-extension.ts} +99 -105
  64. package/src/packlets/invitations/invitation-protocol.ts +7 -1
  65. package/src/packlets/invitations/invitation-topology.ts +87 -0
  66. package/src/packlets/invitations/invitations-handler.test.ts +361 -0
  67. package/src/packlets/invitations/invitations-handler.ts +246 -149
  68. package/src/packlets/invitations/invitations-manager.ts +45 -3
  69. package/src/packlets/invitations/space-invitation-protocol.ts +23 -3
  70. package/src/packlets/invitations/utils.ts +27 -0
  71. package/src/packlets/services/automerge-host.test.ts +6 -4
  72. package/src/packlets/services/service-context.test.ts +3 -3
  73. package/src/packlets/services/service-context.ts +18 -31
  74. package/src/packlets/services/service-host.test.ts +6 -0
  75. package/src/packlets/services/service-host.ts +11 -28
  76. package/src/packlets/spaces/data-space-manager.test.ts +4 -4
  77. package/src/packlets/spaces/data-space-manager.ts +8 -11
  78. package/src/packlets/spaces/data-space.ts +16 -19
  79. package/src/packlets/spaces/genesis.ts +1 -1
  80. package/src/packlets/spaces/spaces-service.ts +12 -6
  81. package/src/packlets/storage/level.ts +3 -2
  82. package/src/packlets/testing/invitation-utils.ts +23 -3
  83. package/src/packlets/testing/test-builder.ts +13 -15
  84. package/src/packlets/vault/shell-runtime.ts +40 -2
  85. package/src/packlets/vault/worker-runtime.ts +3 -1
  86. package/src/version.ts +1 -5
  87. package/dist/lib/browser/chunk-ESEYLOPB.mjs.map +0 -7
  88. package/dist/lib/node/chunk-GA7JFIXK.cjs.map +0 -7
  89. package/dist/types/src/packlets/indexing/index.d.ts +0 -2
  90. package/dist/types/src/packlets/indexing/index.d.ts.map +0 -1
  91. package/dist/types/src/packlets/indexing/util.d.ts +0 -11
  92. package/dist/types/src/packlets/indexing/util.d.ts.map +0 -1
  93. package/dist/types/src/packlets/invitations/invitation-extension.d.ts.map +0 -1
  94. package/src/packlets/indexing/index.ts +0 -5
  95. package/src/packlets/indexing/util.ts +0 -32
@@ -6,14 +6,10 @@ import { Event, asyncTimeout, scheduleTask, sleep, synchronized, trackLeaks } fr
6
6
  import { AUTH_TIMEOUT } from '@dxos/client-protocol';
7
7
  import { cancelWithContext, Context, ContextDisposedError } from '@dxos/context';
8
8
  import { timed, warnAfterTimeout } from '@dxos/debug';
9
- import {
10
- type MetadataStore,
11
- type Space,
12
- createMappedFeedWriter,
13
- type AutomergeHost,
14
- type SpaceDoc,
15
- } from '@dxos/echo-pipeline';
9
+ import { type EchoHost } from '@dxos/echo-db';
10
+ import { type MetadataStore, type Space, createMappedFeedWriter } from '@dxos/echo-pipeline';
16
11
  import { AutomergeDocumentLoaderImpl } from '@dxos/echo-pipeline';
12
+ import { type SpaceDoc } from '@dxos/echo-protocol';
17
13
  import { TYPE_PROPERTIES } from '@dxos/echo-schema';
18
14
  import { type FeedStore } from '@dxos/feed-store';
19
15
  import { failedInvariant, invariant } from '@dxos/invariant';
@@ -24,6 +20,7 @@ import { CancelledError, SystemError } from '@dxos/protocols';
24
20
  import { SpaceState, type Space as SpaceProto, CreateEpochRequest } from '@dxos/protocols/proto/dxos/client/services';
25
21
  import { type FeedMessage } from '@dxos/protocols/proto/dxos/echo/feed';
26
22
  import { type SpaceCache } from '@dxos/protocols/proto/dxos/echo/metadata';
23
+ import { SpaceMember } from '@dxos/protocols/proto/dxos/halo/credentials';
27
24
  import {
28
25
  AdmittedFeed,
29
26
  type ProfileDocument,
@@ -66,10 +63,10 @@ export type DataSpaceParams = {
66
63
  presence: Presence;
67
64
  keyring: Keyring;
68
65
  feedStore: FeedStore<FeedMessage>;
66
+ echoHost: EchoHost;
69
67
  signingContext: SigningContext;
70
68
  callbacks?: DataSpaceCallbacks;
71
69
  cache?: SpaceCache;
72
- automergeHost: AutomergeHost;
73
70
  };
74
71
 
75
72
  export type CreateEpochOptions = {
@@ -92,7 +89,7 @@ export class DataSpace {
92
89
  private readonly _notarizationPlugin = new NotarizationPlugin();
93
90
  private readonly _callbacks: DataSpaceCallbacks;
94
91
  private readonly _cache?: SpaceCache = undefined;
95
- private readonly _automergeHost: AutomergeHost;
92
+ private readonly _echoHost: EchoHost;
96
93
 
97
94
  // TODO(dmaretskyi): Move into Space?
98
95
  private readonly _automergeSpaceState = new AutomergeSpaceState((rootUrl) => this._onNewAutomergeRoot(rootUrl));
@@ -120,14 +117,14 @@ export class DataSpace {
120
117
  this._metadataStore = params.metadataStore;
121
118
  this._signingContext = params.signingContext;
122
119
  this._callbacks = params.callbacks ?? {};
123
- this._automergeHost = params.automergeHost;
120
+ this._echoHost = params.echoHost;
124
121
 
125
122
  this.authVerifier = new TrustedKeySetAuthVerifier({
126
123
  trustedKeysProvider: () =>
127
124
  new ComplexSet(
128
125
  PublicKey.hash,
129
126
  Array.from(this._inner.spaceState.members.values())
130
- .filter((member) => !member.removed)
127
+ .filter((member) => member.role !== SpaceMember.Role.REMOVED)
131
128
  .map((member) => member.key),
132
129
  ),
133
130
  update: this._inner.stateUpdate,
@@ -363,8 +360,8 @@ export class DataSpace {
363
360
 
364
361
  private _onNewAutomergeRoot(rootUrl: string) {
365
362
  log('loading automerge root doc for space', { space: this.key, rootUrl });
366
- this._automergeHost._requestedDocs.add(rootUrl as any);
367
- const handle = this._automergeHost.repo.find(rootUrl as any);
363
+ this._echoHost.replicateDocument(rootUrl);
364
+ const handle = this._echoHost.automergeRepo.find(rootUrl as any);
368
365
 
369
366
  queueMicrotask(async () => {
370
367
  try {
@@ -419,7 +416,7 @@ export class DataSpace {
419
416
  break;
420
417
  case CreateEpochRequest.Migration.INIT_AUTOMERGE:
421
418
  {
422
- const document = this._automergeHost.repo.create();
419
+ const document = this._echoHost.automergeRepo.create();
423
420
  // TODO(dmaretskyi): Unify epoch construction.
424
421
  epoch = {
425
422
  previousId: this._automergeSpaceState.lastEpoch?.id,
@@ -432,9 +429,9 @@ export class DataSpace {
432
429
  case CreateEpochRequest.Migration.PRUNE_AUTOMERGE_ROOT_HISTORY:
433
430
  {
434
431
  const currentRootUrl = this._automergeSpaceState.rootUrl;
435
- const rootHandle = this._automergeHost.repo.find(currentRootUrl as any);
432
+ const rootHandle = this._echoHost.automergeRepo.find(currentRootUrl as any);
436
433
  await cancelWithContext(this._ctx, asyncTimeout(rootHandle.whenReady(), 10_000));
437
- const newRoot = this._automergeHost.repo.create(rootHandle.docSync());
434
+ const newRoot = this._echoHost.automergeRepo.create(rootHandle.docSync());
438
435
  invariant(typeof newRoot.url === 'string' && newRoot.url.length > 0);
439
436
  // TODO(dmaretskyi): Unify epoch construction.
440
437
  epoch = {
@@ -450,7 +447,7 @@ export class DataSpace {
450
447
  log.info('Fragmenting');
451
448
 
452
449
  const currentRootUrl = this._automergeSpaceState.rootUrl;
453
- const rootHandle = this._automergeHost.repo.find<SpaceDoc>(currentRootUrl as any);
450
+ const rootHandle = this._echoHost.automergeRepo.find<SpaceDoc>(currentRootUrl as any);
454
451
  await cancelWithContext(this._ctx, asyncTimeout(rootHandle.whenReady(), 10_000));
455
452
 
456
453
  // Find properties object.
@@ -461,11 +458,11 @@ export class DataSpace {
461
458
 
462
459
  // Create a new space doc with the properties object.
463
460
  const newSpaceDoc: SpaceDoc = { ...rootHandle.docSync(), objects: Object.fromEntries([properties]) };
464
- const newRoot = this._automergeHost.repo.create(newSpaceDoc);
461
+ const newRoot = this._echoHost.automergeRepo.create(newSpaceDoc);
465
462
  invariant(typeof newRoot.url === 'string' && newRoot.url.length > 0);
466
463
 
467
464
  // Create new automerge documents for all objects.
468
- const docLoader = new AutomergeDocumentLoaderImpl(this.key, this._automergeHost.repo);
465
+ const docLoader = new AutomergeDocumentLoaderImpl(this.key, this._echoHost.automergeRepo);
469
466
  await docLoader.loadSpaceRootDocHandle(this._ctx, { rootUrl: newRoot.url });
470
467
 
471
468
  otherObjects.forEach(([key, value]) => {
@@ -36,7 +36,7 @@ export const spaceGenesis = async (
36
36
  assertion: {
37
37
  '@type': 'dxos.halo.credentials.SpaceMember',
38
38
  spaceKey: space.key,
39
- role: SpaceMember.Role.ADMIN,
39
+ role: SpaceMember.Role.OWNER,
40
40
  profile: signingContext.getProfile(),
41
41
  genesisFeedKey: space.controlFeedKey ?? failUndefined(),
42
42
  },
@@ -22,8 +22,9 @@ import {
22
22
  type SubscribeMessagesRequest,
23
23
  type UpdateSpaceRequest,
24
24
  type WriteCredentialsRequest,
25
+ type UpdateMemberRoleRequest,
25
26
  } from '@dxos/protocols/proto/dxos/client/services';
26
- import { type Credential } from '@dxos/protocols/proto/dxos/halo/credentials';
27
+ import { type Credential, SpaceMember as HaloSpaceMember } from '@dxos/protocols/proto/dxos/halo/credentials';
27
28
  import { type GossipMessage } from '@dxos/protocols/proto/dxos/mesh/teleport/gossip';
28
29
  import { type Provider } from '@dxos/util';
29
30
 
@@ -67,6 +68,10 @@ export class SpacesServiceImpl implements SpacesService {
67
68
  }
68
69
  }
69
70
 
71
+ async updateMemberRole(_: UpdateMemberRoleRequest): Promise<void> {
72
+ throw new Error('not implemented');
73
+ }
74
+
70
75
  querySpaces(): Stream<QuerySpacesResponse> {
71
76
  return new Stream<QuerySpacesResponse>(({ next, ctx }) => {
72
77
  const scheduler = new UpdateScheduler(
@@ -213,11 +218,12 @@ export class SpacesServiceImpl implements SpacesService {
213
218
  identityKey: member.key,
214
219
  profile: member.profile ?? {},
215
220
  },
216
- presence: member.removed
217
- ? SpaceMember.PresenceState.REMOVED
218
- : isMe || peers.length > 0
219
- ? SpaceMember.PresenceState.ONLINE
220
- : SpaceMember.PresenceState.OFFLINE,
221
+ presence:
222
+ member.role === HaloSpaceMember.Role.REMOVED
223
+ ? SpaceMember.PresenceState.REMOVED
224
+ : isMe || peers.length > 0
225
+ ? SpaceMember.PresenceState.ONLINE
226
+ : SpaceMember.PresenceState.OFFLINE,
221
227
  peerStates: peers,
222
228
  };
223
229
  }),
@@ -2,10 +2,10 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { Level } from 'level';
6
5
  import path from 'node:path';
7
6
 
8
7
  import { PublicKey } from '@dxos/keys';
8
+ import { createLevel as createKV } from '@dxos/kv-store';
9
9
  import { type Runtime } from '@dxos/protocols/proto/dxos/config';
10
10
 
11
11
  import { getRootPath, isPersistent } from './util';
@@ -13,7 +13,8 @@ import { getRootPath, isPersistent } from './util';
13
13
  export const createLevel = async (config: Runtime.Client.Storage) => {
14
14
  const persistent = isPersistent(config);
15
15
  const storagePath = persistent ? path.join(getRootPath(config), 'level') : `/tmp/dxos-${PublicKey.random().toHex()}`;
16
- const level = new Level<string, string>(storagePath);
16
+ const level = createKV(storagePath);
17
+ // TODO(dmaretskyi): This function shouldn't call open - .
17
18
  await level.open();
18
19
  return level;
19
20
  };
@@ -45,6 +45,7 @@ export type PerformInvitationParams = {
45
45
  guest?: PerformInvitationCallbacks<AuthenticatingInvitation>;
46
46
  };
47
47
  guestDeviceProfile?: DeviceProfileDocument;
48
+ codeInputDelay?: number;
48
49
  };
49
50
 
50
51
  export type Result = { invitation?: Invitation; error?: Error };
@@ -55,7 +56,10 @@ export const performInvitation = ({
55
56
  options,
56
57
  hooks,
57
58
  guestDeviceProfile,
59
+ codeInputDelay,
58
60
  }: PerformInvitationParams): [Promise<Result>, Promise<Result>] => {
61
+ let guestError = false;
62
+ let guestConnected = false;
59
63
  const hostComplete = new Trigger<Result>();
60
64
  const guestComplete = new Trigger<Result>();
61
65
  const authCode = new Trigger<string>();
@@ -65,6 +69,10 @@ export const performInvitation = ({
65
69
  async (hostInvitation: Invitation) => {
66
70
  switch (hostInvitation.state) {
67
71
  case Invitation.State.CONNECTING: {
72
+ if (guestConnected) {
73
+ break;
74
+ }
75
+ guestConnected = true;
68
76
  if (hooks?.host?.onConnecting?.(hostObservable)) {
69
77
  break;
70
78
  }
@@ -89,7 +97,16 @@ export const performInvitation = ({
89
97
  if (hooks?.guest?.onReady?.(guestObservable)) {
90
98
  break;
91
99
  }
92
- await guestObservable.authenticate(await authCode.wait());
100
+ const code = await authCode.wait();
101
+ if (codeInputDelay == null) {
102
+ await guestObservable.authenticate(code);
103
+ } else {
104
+ setTimeout(async () => {
105
+ if (!guestError) {
106
+ await guestObservable.authenticate(code);
107
+ }
108
+ }, codeInputDelay);
109
+ }
93
110
  break;
94
111
  }
95
112
 
@@ -123,6 +140,7 @@ export const performInvitation = ({
123
140
  }
124
141
  },
125
142
  (error: Error) => {
143
+ guestError = true;
126
144
  if (hooks?.guest?.onError?.(guestObservable)) {
127
145
  return;
128
146
  }
@@ -216,8 +234,10 @@ const acceptInvitation = (
216
234
  invitation = sanitizeInvitation(invitation);
217
235
 
218
236
  if (guest instanceof ServiceContext) {
219
- const guestHandler = guest.getInvitationHandler({ kind: invitation.kind });
220
- return guest.invitations.acceptInvitation(guestHandler, invitation, guestDeviceProfile);
237
+ return guest.invitationsManager.acceptInvitation({
238
+ invitation,
239
+ deviceProfile: guestDeviceProfile,
240
+ });
221
241
  }
222
242
 
223
243
  return guest.join(invitation, guestDeviceProfile);
@@ -6,17 +6,12 @@ import { type Config } from '@dxos/config';
6
6
  import { Context } from '@dxos/context';
7
7
  import { createCredentialSignerWithChain, CredentialGenerator } from '@dxos/credentials';
8
8
  import { failUndefined } from '@dxos/debug';
9
- import {
10
- AutomergeHost,
11
- MetadataStore,
12
- type LevelDB,
13
- SnapshotStore,
14
- SpaceManager,
15
- valueEncoding,
16
- } from '@dxos/echo-pipeline';
17
- import { createTestLevel } from '@dxos/echo-pipeline/testing';
9
+ import { EchoHost } from '@dxos/echo-db';
10
+ import { MetadataStore, SnapshotStore, SpaceManager, valueEncoding } from '@dxos/echo-pipeline';
18
11
  import { FeedFactory, FeedStore } from '@dxos/feed-store';
19
12
  import { Keyring } from '@dxos/keyring';
13
+ import { type LevelDB } from '@dxos/kv-store';
14
+ import { createTestLevel } from '@dxos/kv-store/testing';
20
15
  import { MemorySignalManager, MemorySignalManagerContext } from '@dxos/messaging';
21
16
  import { MemoryTransportFactory, NetworkManager } from '@dxos/network-manager';
22
17
  import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
@@ -54,7 +49,9 @@ export const createServiceContext = async ({
54
49
  const level = createTestLevel();
55
50
  await level.open();
56
51
 
57
- return new ServiceContext(storage, level, networkManager, signalManager);
52
+ return new ServiceContext(storage, level, networkManager, signalManager, {
53
+ invitationConnectionDefaultParams: { controlHeartbeatInterval: 200 },
54
+ });
58
55
  };
59
56
 
60
57
  export const createPeers = async (numPeers: number) => {
@@ -105,7 +102,7 @@ export type TestPeerProps = {
105
102
  snapshotStore?: SnapshotStore;
106
103
  signingContext?: SigningContext;
107
104
  blobStore?: BlobStore;
108
- automergeHost?: AutomergeHost;
105
+ echoHost?: EchoHost;
109
106
  invitationsManager?: InvitationsManager;
110
107
  };
111
108
 
@@ -178,9 +175,10 @@ export class TestPeer {
178
175
  return this._props.signingContext ?? failUndefined();
179
176
  }
180
177
 
181
- get automergeHost() {
182
- return (this._props.automergeHost ??= new AutomergeHost({
183
- db: this.level.sublevel('automerge'),
178
+ get echoHost() {
179
+ return (this._props.echoHost ??= new EchoHost({
180
+ kv: this.level,
181
+ storage: this.storage,
184
182
  }));
185
183
  }
186
184
 
@@ -191,7 +189,7 @@ export class TestPeer {
191
189
  this.keyring,
192
190
  this.identity,
193
191
  this.feedStore,
194
- this.automergeHost,
192
+ this.echoHost,
195
193
  this.invitationsManager,
196
194
  ));
197
195
  }
@@ -6,7 +6,12 @@ import { Event } from '@dxos/async';
6
6
  import { appServiceBundle, type AppServiceBundle, type ShellRuntime, shellServiceBundle } from '@dxos/client-protocol';
7
7
  import { invariant } from '@dxos/invariant';
8
8
  import { type PublicKey } from '@dxos/keys';
9
- import { type AppContextRequest, type LayoutRequest, ShellLayout } from '@dxos/protocols/proto/dxos/iframe';
9
+ import {
10
+ type AppContextRequest,
11
+ type LayoutRequest,
12
+ ShellLayout,
13
+ type InvitationUrlRequest,
14
+ } from '@dxos/protocols/proto/dxos/iframe';
10
15
  import { createProtoRpcPeer, type ProtoRpcPeer, type RpcPort } from '@dxos/rpc';
11
16
 
12
17
  /**
@@ -14,11 +19,19 @@ import { createProtoRpcPeer, type ProtoRpcPeer, type RpcPort } from '@dxos/rpc';
14
19
  */
15
20
  export class ShellRuntimeImpl implements ShellRuntime {
16
21
  readonly layoutUpdate = new Event<LayoutRequest>();
22
+ readonly invitationUrlUpdate = new Event<InvitationUrlRequest>();
23
+
17
24
  private _appRpc?: ProtoRpcPeer<AppServiceBundle>;
18
25
  private _layout = ShellLayout.DEFAULT;
19
- private _invitationCode?: string;
20
26
  private _spaceKey?: PublicKey;
21
27
 
28
+ private _invitationCode?: string;
29
+ private _invitationUrl? = typeof window !== 'undefined' ? window.location.origin : undefined;
30
+
31
+ // TODO(burdon): Change to using underscores (coordinate with @dxos/web-auth).
32
+ private _deviceInvitationParam = 'deviceInvitationCode'; // TODO(burdon): device_invitation_code
33
+ private _spaceInvitationParam = 'spaceInvitationCode'; // TODO(burdon): space_invitation_code
34
+
22
35
  constructor(private readonly _port: RpcPort) {}
23
36
 
24
37
  get layout() {
@@ -33,6 +46,18 @@ export class ShellRuntimeImpl implements ShellRuntime {
33
46
  return this._spaceKey;
34
47
  }
35
48
 
49
+ get invitationUrl() {
50
+ return this._invitationUrl!;
51
+ }
52
+
53
+ get deviceInvitationParam() {
54
+ return this._deviceInvitationParam;
55
+ }
56
+
57
+ get spaceInvitationParam() {
58
+ return this._spaceInvitationParam;
59
+ }
60
+
36
61
  setLayout({ layout, invitationCode, spaceKey }: LayoutRequest) {
37
62
  this._layout = layout;
38
63
  this._invitationCode = invitationCode;
@@ -40,6 +65,13 @@ export class ShellRuntimeImpl implements ShellRuntime {
40
65
  this.layoutUpdate.emit({ layout, invitationCode, spaceKey });
41
66
  }
42
67
 
68
+ setInvitationUrl({ invitationUrl, deviceInvitationParam, spaceInvitationParam }: InvitationUrlRequest) {
69
+ this._invitationUrl = invitationUrl;
70
+ this._deviceInvitationParam = deviceInvitationParam;
71
+ this._spaceInvitationParam = spaceInvitationParam;
72
+ this.invitationUrlUpdate.emit({ invitationUrl, deviceInvitationParam, spaceInvitationParam });
73
+ }
74
+
43
75
  async setAppContext(context: AppContextRequest) {
44
76
  invariant(this._appRpc, 'runtime not open');
45
77
 
@@ -58,6 +90,12 @@ export class ShellRuntimeImpl implements ShellRuntime {
58
90
  this._spaceKey = request.spaceKey;
59
91
  this.layoutUpdate.emit(request);
60
92
  },
93
+ setInvitationUrl: async (request) => {
94
+ this._invitationUrl = request.invitationUrl;
95
+ this._deviceInvitationParam = request.deviceInvitationParam;
96
+ this._spaceInvitationParam = request.spaceInvitationParam;
97
+ this.invitationUrlUpdate.emit(request);
98
+ },
61
99
  },
62
100
  },
63
101
  port: this._port,
@@ -120,7 +120,9 @@ export class WorkerRuntime {
120
120
  this._sessions.delete(session);
121
121
  if (this._sessions.size === 0) {
122
122
  // Terminate the worker when all sessions are closed.
123
- self.close();
123
+ if (globalThis.self) {
124
+ self.close();
125
+ }
124
126
  } else {
125
127
  this._reconnectWebrtc();
126
128
  }
package/src/version.ts CHANGED
@@ -1,5 +1 @@
1
- //
2
- // Copyright 2023 DXOS.org
3
- //
4
-
5
- export const DXOS_VERSION = '0.5.0'; // {x-release-please-version}
1
+ export const DXOS_VERSION = "0.5.1-main.0ec204c";