@dxos/client-services 0.8.4-main.c4373fc → 0.8.4-main.c85a9c8dae
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-HWGM5TYF.mjs → chunk-MQ6PWJ76.mjs} +1936 -2336
- package/dist/lib/browser/chunk-MQ6PWJ76.mjs.map +7 -0
- package/dist/lib/browser/chunk-NQSC7HOE.mjs +22 -0
- package/dist/lib/browser/chunk-NQSC7HOE.mjs.map +7 -0
- package/dist/lib/browser/chunk-QCWEHHJW.mjs +24 -0
- package/dist/lib/browser/chunk-QCWEHHJW.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +522 -172
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/packlets/diagnostics/browser-diagnostics-broadcast.mjs +93 -0
- package/dist/lib/browser/packlets/diagnostics/browser-diagnostics-broadcast.mjs.map +7 -0
- package/dist/lib/browser/packlets/diagnostics/diagnostics-broadcast.mjs +11 -0
- package/dist/lib/browser/packlets/diagnostics/diagnostics-broadcast.mjs.map +7 -0
- package/dist/lib/browser/packlets/locks/browser.mjs +126 -0
- package/dist/lib/browser/packlets/locks/browser.mjs.map +7 -0
- package/dist/lib/browser/packlets/locks/node.mjs +66 -0
- package/dist/lib/browser/packlets/locks/node.mjs.map +7 -0
- package/dist/lib/browser/testing/index.mjs +59 -76
- package/dist/lib/browser/testing/index.mjs.map +3 -3
- package/dist/lib/node-esm/chunk-2SZHAWBN.mjs +24 -0
- package/dist/lib/node-esm/chunk-2SZHAWBN.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-XUIY55CH.mjs → chunk-GUAL4U7S.mjs} +1468 -1737
- package/dist/lib/node-esm/chunk-GUAL4U7S.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-PKEGMOQ4.mjs +22 -0
- package/dist/lib/node-esm/chunk-PKEGMOQ4.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +522 -172
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/packlets/diagnostics/browser-diagnostics-broadcast.mjs +93 -0
- package/dist/lib/node-esm/packlets/diagnostics/browser-diagnostics-broadcast.mjs.map +7 -0
- package/dist/lib/node-esm/packlets/diagnostics/diagnostics-broadcast.mjs +11 -0
- package/dist/lib/node-esm/packlets/diagnostics/diagnostics-broadcast.mjs.map +7 -0
- package/dist/lib/node-esm/packlets/locks/browser.mjs +126 -0
- package/dist/lib/node-esm/packlets/locks/browser.mjs.map +7 -0
- package/dist/lib/node-esm/packlets/locks/node.mjs +66 -0
- package/dist/lib/node-esm/packlets/locks/node.mjs.map +7 -0
- package/dist/lib/node-esm/testing/index.mjs +59 -76
- package/dist/lib/node-esm/testing/index.mjs.map +3 -3
- package/dist/types/src/packlets/agents/edge-agent-service.d.ts.map +1 -1
- package/dist/types/src/packlets/devtools/devtools.d.ts +2 -2
- package/dist/types/src/packlets/devtools/devtools.d.ts.map +1 -1
- package/dist/types/src/packlets/diagnostics/index.d.ts +1 -1
- package/dist/types/src/packlets/diagnostics/index.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/authenticator.d.ts +2 -2
- package/dist/types/src/packlets/identity/authenticator.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/default-space-state-machine.d.ts +2 -2
- package/dist/types/src/packlets/identity/default-space-state-machine.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity-manager.d.ts +4 -4
- package/dist/types/src/packlets/identity/identity-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts +2 -2
- package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity.d.ts +2 -2
- package/dist/types/src/packlets/identity/identity.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts +4 -4
- package/dist/types/src/packlets/invitations/device-invitation-protocol.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 +2 -3
- package/dist/types/src/packlets/invitations/invitation-protocol.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitations-handler.d.ts +4 -4
- package/dist/types/src/packlets/invitations/invitations-handler.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts +2 -2
- package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts.map +1 -1
- package/dist/types/src/packlets/locks/index.d.ts +1 -1
- package/dist/types/src/packlets/locks/index.d.ts.map +1 -1
- package/dist/types/src/packlets/logging/logging-service.d.ts +4 -0
- package/dist/types/src/packlets/logging/logging-service.d.ts.map +1 -1
- package/dist/types/src/packlets/services/client-rpc-server.d.ts +2 -2
- package/dist/types/src/packlets/services/client-rpc-server.d.ts.map +1 -1
- package/dist/types/src/packlets/services/feed-syncer.d.ts +59 -0
- package/dist/types/src/packlets/services/feed-syncer.d.ts.map +1 -0
- package/dist/types/src/packlets/services/feed-syncer.test.d.ts +2 -0
- package/dist/types/src/packlets/services/feed-syncer.test.d.ts.map +1 -0
- package/dist/types/src/packlets/services/platform.d.ts.map +1 -1
- package/dist/types/src/packlets/services/service-context.d.ts +12 -7
- package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
- package/dist/types/src/packlets/services/service-host.d.ts +19 -5
- package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
- package/dist/types/src/packlets/space-export/space-archive-writer.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/data-space-manager.d.ts +10 -5
- package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/data-space.d.ts +2 -2
- package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts +2 -2
- package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/notarization-plugin.d.ts +6 -6
- package/dist/types/src/packlets/spaces/notarization-plugin.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/spaces-service.d.ts.map +1 -1
- package/dist/types/src/packlets/testing/invitation-utils.d.ts +6 -3
- package/dist/types/src/packlets/testing/invitation-utils.d.ts.map +1 -1
- package/dist/types/src/packlets/testing/test-builder.d.ts +6 -5
- package/dist/types/src/packlets/testing/test-builder.d.ts.map +1 -1
- package/dist/types/src/packlets/worker/worker-runtime.d.ts +31 -4
- package/dist/types/src/packlets/worker/worker-runtime.d.ts.map +1 -1
- package/dist/types/src/packlets/worker/worker-session.d.ts +2 -2
- package/dist/types/src/packlets/worker/worker-session.d.ts.map +1 -1
- package/dist/types/src/version.d.ts +1 -1
- package/dist/types/src/version.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +70 -48
- package/src/packlets/agents/edge-agent-service.ts +11 -1
- package/src/packlets/devices/devices-service.ts +1 -1
- package/src/packlets/devtools/devtools.ts +2 -2
- package/src/packlets/diagnostics/index.ts +1 -1
- package/src/packlets/identity/authenticator.ts +2 -2
- package/src/packlets/identity/default-space-state-machine.ts +2 -2
- package/src/packlets/identity/identity-manager.ts +6 -6
- package/src/packlets/identity/identity-recovery-manager.ts +2 -2
- package/src/packlets/identity/identity.test.ts +4 -4
- package/src/packlets/identity/identity.ts +2 -2
- package/src/packlets/invitations/device-invitation-protocol.ts +5 -5
- package/src/packlets/invitations/invitation-guest-extenstion.ts +6 -4
- package/src/packlets/invitations/invitation-host-extension.ts +6 -4
- package/src/packlets/invitations/invitation-protocol.ts +2 -3
- package/src/packlets/invitations/invitations-handler.ts +7 -7
- package/src/packlets/invitations/space-invitation-protocol.ts +7 -13
- package/src/packlets/locks/index.ts +1 -1
- package/src/packlets/logging/logging-service.ts +5 -1
- package/src/packlets/services/client-rpc-server.ts +4 -4
- package/src/packlets/services/feed-syncer.test.ts +340 -0
- package/src/packlets/services/feed-syncer.ts +330 -0
- package/src/packlets/services/platform.ts +7 -1
- package/src/packlets/services/service-context.ts +53 -21
- package/src/packlets/services/service-host.ts +53 -16
- package/src/packlets/space-export/space-archive-reader.ts +1 -1
- package/src/packlets/space-export/space-archive-writer.ts +3 -1
- package/src/packlets/spaces/data-space-manager.ts +56 -21
- package/src/packlets/spaces/data-space.ts +10 -6
- package/src/packlets/spaces/edge-feed-replicator.test.ts +1 -1
- package/src/packlets/spaces/edge-feed-replicator.ts +3 -3
- package/src/packlets/spaces/epoch-migrations.ts +2 -2
- package/src/packlets/spaces/notarization-plugin.test.ts +2 -2
- package/src/packlets/spaces/notarization-plugin.ts +8 -8
- package/src/packlets/spaces/spaces-service.ts +10 -7
- package/src/packlets/storage/storage.ts +4 -4
- package/src/packlets/testing/invitation-utils.ts +7 -4
- package/src/packlets/testing/test-builder.ts +36 -10
- package/src/packlets/worker/worker-runtime.ts +149 -11
- package/src/packlets/worker/worker-session.ts +8 -8
- package/src/version.ts +1 -1
- package/dist/lib/browser/chunk-HWGM5TYF.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-XUIY55CH.mjs.map +0 -7
|
@@ -22,7 +22,7 @@ import type { FeedBlock, ProtocolMessage } from '@dxos/protocols/feed-replicatio
|
|
|
22
22
|
import { EdgeStatus } from '@dxos/protocols/proto/dxos/client/services';
|
|
23
23
|
import { ComplexMap, arrayToBuffer, bufferToArray, defaultMap, rangeFromTo } from '@dxos/util';
|
|
24
24
|
|
|
25
|
-
export type
|
|
25
|
+
export type EdgeFeedReplicatorProps = {
|
|
26
26
|
messenger: EdgeConnection;
|
|
27
27
|
spaceId: SpaceId;
|
|
28
28
|
};
|
|
@@ -47,7 +47,7 @@ export class EdgeFeedReplicator extends Resource {
|
|
|
47
47
|
*/
|
|
48
48
|
private _pushMutex = new ComplexMap<PublicKey, Mutex>(PublicKey.hash);
|
|
49
49
|
|
|
50
|
-
constructor({ messenger, spaceId }:
|
|
50
|
+
constructor({ messenger, spaceId }: EdgeFeedReplicatorProps) {
|
|
51
51
|
super();
|
|
52
52
|
this._messenger = messenger;
|
|
53
53
|
this._spaceId = spaceId;
|
|
@@ -87,7 +87,7 @@ export class EdgeFeedReplicator extends Resource {
|
|
|
87
87
|
|
|
88
88
|
private async _handleReconnect(): Promise<void> {
|
|
89
89
|
await this._resetConnection();
|
|
90
|
-
if (this._messenger.status === EdgeStatus.CONNECTED) {
|
|
90
|
+
if (this._messenger.status.state === EdgeStatus.ConnectionState.CONNECTED) {
|
|
91
91
|
this._startReplication();
|
|
92
92
|
}
|
|
93
93
|
}
|
|
@@ -36,7 +36,7 @@ const LOAD_DOC_TIMEOUT = 10_000;
|
|
|
36
36
|
export const runEpochMigration = async (ctx: Context, context: MigrationContext): Promise<MigrationResult> => {
|
|
37
37
|
switch (context.migration) {
|
|
38
38
|
case CreateEpochRequest.Migration.INIT_AUTOMERGE: {
|
|
39
|
-
const document = context.echoHost.createDoc();
|
|
39
|
+
const document = await context.echoHost.createDoc();
|
|
40
40
|
await context.echoHost.flush();
|
|
41
41
|
return { newRoot: document.url };
|
|
42
42
|
}
|
|
@@ -48,7 +48,7 @@ export const runEpochMigration = async (ctx: Context, context: MigrationContext)
|
|
|
48
48
|
timeout: LOAD_DOC_TIMEOUT,
|
|
49
49
|
});
|
|
50
50
|
|
|
51
|
-
const newRoot = context.echoHost.createDoc(rootHandle.doc());
|
|
51
|
+
const newRoot = await context.echoHost.createDoc(rootHandle.doc());
|
|
52
52
|
await context.echoHost.flush();
|
|
53
53
|
return { newRoot: newRoot.url };
|
|
54
54
|
}
|
|
@@ -13,7 +13,7 @@ import { log } from '@dxos/log';
|
|
|
13
13
|
import { AdmittedFeed, type Credential } from '@dxos/protocols/proto/dxos/halo/credentials';
|
|
14
14
|
import { TestBuilder, type TestConnection, TestPeer } from '@dxos/teleport/testing';
|
|
15
15
|
|
|
16
|
-
import { NotarizationPlugin, type
|
|
16
|
+
import { NotarizationPlugin, type NotarizationPluginProps } from './notarization-plugin';
|
|
17
17
|
|
|
18
18
|
class TestAgent extends TestPeer {
|
|
19
19
|
private readonly _ctx = new Context();
|
|
@@ -21,7 +21,7 @@ class TestAgent extends TestPeer {
|
|
|
21
21
|
feed = new MockFeedWriter<Credential>();
|
|
22
22
|
notarizationPlugin: NotarizationPlugin;
|
|
23
23
|
|
|
24
|
-
constructor(params:
|
|
24
|
+
constructor(params: NotarizationPluginProps) {
|
|
25
25
|
super();
|
|
26
26
|
this.notarizationPlugin = new NotarizationPlugin(params);
|
|
27
27
|
this.feed.written.on(this._ctx, async ([credential]) => {
|
|
@@ -33,14 +33,14 @@ const WRITER_NOT_SET_ERROR_CODE = 'WRITER_NOT_SET';
|
|
|
33
33
|
|
|
34
34
|
const credentialCodec = schema.getCodecForType('dxos.halo.credentials.Credential');
|
|
35
35
|
|
|
36
|
-
export type
|
|
36
|
+
export type NotarizationPluginProps = {
|
|
37
37
|
spaceId: SpaceId;
|
|
38
38
|
edgeClient?: EdgeHttpClient;
|
|
39
39
|
edgeFeatures?: Runtime.Client.EdgeFeatures;
|
|
40
40
|
activeEdgePollingInterval?: number;
|
|
41
41
|
};
|
|
42
42
|
|
|
43
|
-
export type
|
|
43
|
+
export type NotarizeProps = {
|
|
44
44
|
/**
|
|
45
45
|
* For cancellation.
|
|
46
46
|
*/
|
|
@@ -97,7 +97,7 @@ export class NotarizationPlugin extends Resource implements CredentialProcessor
|
|
|
97
97
|
|
|
98
98
|
private readonly _edgeClient: EdgeHttpClient | undefined;
|
|
99
99
|
|
|
100
|
-
constructor(params:
|
|
100
|
+
constructor(params: NotarizationPluginProps) {
|
|
101
101
|
super();
|
|
102
102
|
this._spaceId = params.spaceId;
|
|
103
103
|
this._activeEdgePollingInterval = params.activeEdgePollingInterval ?? DEFAULT_ACTIVE_EDGE_POLLING_INTERVAL;
|
|
@@ -149,7 +149,7 @@ export class NotarizationPlugin extends Resource implements CredentialProcessor
|
|
|
149
149
|
retryTimeout = DEFAULT_RETRY_TIMEOUT,
|
|
150
150
|
successDelay = DEFAULT_SUCCESS_DELAY,
|
|
151
151
|
edgeRetryJitter,
|
|
152
|
-
}:
|
|
152
|
+
}: NotarizeProps): Promise<void> {
|
|
153
153
|
log('notarize', { credentials });
|
|
154
154
|
invariant(
|
|
155
155
|
credentials.every((credential) => credential.id),
|
|
@@ -392,21 +392,21 @@ export class NotarizationPlugin extends Resource implements CredentialProcessor
|
|
|
392
392
|
}
|
|
393
393
|
|
|
394
394
|
const handleEdgeError = (error: any) => {
|
|
395
|
-
if (!(error instanceof EdgeCallFailedError) || error.
|
|
395
|
+
if (!(error instanceof EdgeCallFailedError) || error.data) {
|
|
396
396
|
log.catch(error);
|
|
397
397
|
} else {
|
|
398
|
-
log.info('Edge notarization failure', {
|
|
398
|
+
log.info('Edge notarization failure', { message: error.message });
|
|
399
399
|
}
|
|
400
400
|
};
|
|
401
401
|
|
|
402
|
-
export type
|
|
402
|
+
export type NotarizationTeleportExtensionProps = {
|
|
403
403
|
onOpen: () => Promise<void>;
|
|
404
404
|
onClose: () => Promise<void>;
|
|
405
405
|
onNotarize: (request: NotarizeRequest) => Promise<void>;
|
|
406
406
|
};
|
|
407
407
|
|
|
408
408
|
export class NotarizationTeleportExtension extends RpcExtension<Services, Services> {
|
|
409
|
-
constructor(private readonly _params:
|
|
409
|
+
constructor(private readonly _params: NotarizationTeleportExtensionProps) {
|
|
410
410
|
super({
|
|
411
411
|
requested: {
|
|
412
412
|
NotarizationService: schema.getService('dxos.mesh.teleport.notarization.NotarizationService'),
|
|
@@ -88,7 +88,7 @@ export class SpacesServiceImpl implements SpacesService {
|
|
|
88
88
|
await space.deactivate();
|
|
89
89
|
break;
|
|
90
90
|
default:
|
|
91
|
-
throw new ApiError('Invalid space state');
|
|
91
|
+
throw new ApiError({ message: 'Invalid space state' });
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
94
|
|
|
@@ -104,9 +104,12 @@ export class SpacesServiceImpl implements SpacesService {
|
|
|
104
104
|
throw new SpaceNotFoundError(request.spaceKey);
|
|
105
105
|
}
|
|
106
106
|
if (!space.spaceState.hasMembershipManagementPermission(identity.identityKey)) {
|
|
107
|
-
throw new AuthorizationError(
|
|
108
|
-
|
|
109
|
-
|
|
107
|
+
throw new AuthorizationError({
|
|
108
|
+
message: 'No member management permission.',
|
|
109
|
+
context: {
|
|
110
|
+
spaceKey: space.key,
|
|
111
|
+
role: space.spaceState.getMemberRole(identity.identityKey),
|
|
112
|
+
},
|
|
110
113
|
});
|
|
111
114
|
}
|
|
112
115
|
const credentials = await createAdmissionCredentials(
|
|
@@ -368,9 +371,9 @@ export class SpacesServiceImpl implements SpacesService {
|
|
|
368
371
|
|
|
369
372
|
private _requireIdentity() {
|
|
370
373
|
if (!this._identityManager.identity) {
|
|
371
|
-
throw new IdentityNotInitializedError(
|
|
372
|
-
'This device has no HALO identity available. See https://docs.dxos.org/guide/platform/halo',
|
|
373
|
-
);
|
|
374
|
+
throw new IdentityNotInitializedError({
|
|
375
|
+
message: 'This device has no HALO identity available. See https://docs.dxos.org/guide/platform/halo',
|
|
376
|
+
});
|
|
374
377
|
}
|
|
375
378
|
return this._identityManager.identity;
|
|
376
379
|
}
|
|
@@ -14,16 +14,16 @@ import StorageDriver = Runtime.Client.Storage.StorageDriver;
|
|
|
14
14
|
export const createStorageObjects = (config: Runtime.Client.Storage) => {
|
|
15
15
|
const { persistent = false, keyStore, dataStore } = config ?? {};
|
|
16
16
|
if (persistent && dataStore === StorageDriver.RAM) {
|
|
17
|
-
throw new InvalidConfigError('RAM storage cannot be used in persistent mode.');
|
|
17
|
+
throw new InvalidConfigError({ message: 'RAM storage cannot be used in persistent mode.' });
|
|
18
18
|
}
|
|
19
19
|
if (!persistent && dataStore !== undefined && dataStore !== StorageDriver.RAM) {
|
|
20
|
-
throw new InvalidConfigError('Cannot use a persistent storage in not persistent mode.');
|
|
20
|
+
throw new InvalidConfigError({ message: 'Cannot use a persistent storage in not persistent mode.' });
|
|
21
21
|
}
|
|
22
22
|
if (persistent && keyStore === StorageDriver.RAM) {
|
|
23
|
-
throw new InvalidConfigError('RAM key storage cannot be used in persistent mode.');
|
|
23
|
+
throw new InvalidConfigError({ message: 'RAM key storage cannot be used in persistent mode.' });
|
|
24
24
|
}
|
|
25
25
|
if (!persistent && keyStore !== StorageDriver.RAM && keyStore !== undefined) {
|
|
26
|
-
throw new InvalidConfigError('Cannot use a persistent key storage in not persistent mode.');
|
|
26
|
+
throw new InvalidConfigError({ message: 'Cannot use a persistent key storage in not persistent mode.' });
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
return {
|
|
@@ -36,15 +36,15 @@ export type PerformInvitationCallbacks<T> = {
|
|
|
36
36
|
onError?: (value: T) => boolean | void;
|
|
37
37
|
};
|
|
38
38
|
|
|
39
|
-
export type
|
|
39
|
+
export type PerformInvitationProps = {
|
|
40
40
|
host: ServiceContext | InvitationHost;
|
|
41
41
|
guest: ServiceContext | InvitationGuest;
|
|
42
|
+
guestDeviceProfile?: DeviceProfileDocument;
|
|
42
43
|
options?: Partial<Invitation>;
|
|
43
44
|
hooks?: {
|
|
44
45
|
host?: PerformInvitationCallbacks<CancellableInvitation>;
|
|
45
46
|
guest?: PerformInvitationCallbacks<AuthenticatingInvitation>;
|
|
46
47
|
};
|
|
47
|
-
guestDeviceProfile?: DeviceProfileDocument;
|
|
48
48
|
codeInputDelay?: number;
|
|
49
49
|
};
|
|
50
50
|
|
|
@@ -52,14 +52,17 @@ export type Result = { invitation?: Invitation; error?: Error };
|
|
|
52
52
|
|
|
53
53
|
// TODO(burdon): Make async.
|
|
54
54
|
// TODO(burdon): Rename startInvitation.
|
|
55
|
+
/**
|
|
56
|
+
*
|
|
57
|
+
*/
|
|
55
58
|
export const performInvitation = ({
|
|
56
59
|
host,
|
|
57
60
|
guest,
|
|
61
|
+
guestDeviceProfile,
|
|
58
62
|
options,
|
|
59
63
|
hooks,
|
|
60
|
-
guestDeviceProfile,
|
|
61
64
|
codeInputDelay,
|
|
62
|
-
}:
|
|
65
|
+
}: PerformInvitationProps): [Promise<Result>, Promise<Result>] => {
|
|
63
66
|
let guestError = false;
|
|
64
67
|
let guestConnected = false;
|
|
65
68
|
let wereConnected = false;
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
// Copyright 2022 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import * as Reactivity from '@effect/experimental/Reactivity';
|
|
6
|
+
import * as Layer from 'effect/Layer';
|
|
7
|
+
import * as ManagedRuntime from 'effect/ManagedRuntime';
|
|
8
|
+
|
|
5
9
|
import { type Config } from '@dxos/config';
|
|
6
10
|
import { Context } from '@dxos/context';
|
|
7
11
|
import { CredentialGenerator, createCredentialSignerWithChain } from '@dxos/credentials';
|
|
@@ -15,11 +19,13 @@ import { MemorySignalManager, MemorySignalManagerContext, type SignalManager } f
|
|
|
15
19
|
import { MemoryTransportFactory, SwarmNetworkManager } from '@dxos/network-manager';
|
|
16
20
|
import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
|
|
17
21
|
import { type Storage, StorageType, createStorage } from '@dxos/random-access-storage';
|
|
22
|
+
import { layerMemory as sqliteLayerMemory } from '@dxos/sql-sqlite/platform';
|
|
23
|
+
import * as SqlTransaction from '@dxos/sql-sqlite/SqlTransaction';
|
|
18
24
|
import { BlobStore } from '@dxos/teleport-extension-object-sync';
|
|
19
25
|
|
|
20
26
|
import { InvitationsHandler, InvitationsManager, SpaceInvitationProtocol } from '../invitations';
|
|
21
|
-
import { ClientServicesHost, ServiceContext, type
|
|
22
|
-
import { DataSpaceManager, type
|
|
27
|
+
import { ClientServicesHost, ServiceContext, type ServiceContextRuntimeProps } from '../services';
|
|
28
|
+
import { DataSpaceManager, type DataSpaceManagerRuntimeProps, type SigningContext } from '../spaces';
|
|
23
29
|
|
|
24
30
|
//
|
|
25
31
|
// TODO(burdon): Replace with test builder.
|
|
@@ -30,6 +36,11 @@ export const createServiceHost = (config: Config, signalManagerContext: MemorySi
|
|
|
30
36
|
config,
|
|
31
37
|
signalManager: new MemorySignalManager(signalManagerContext),
|
|
32
38
|
transportFactory: MemoryTransportFactory,
|
|
39
|
+
runtime: ManagedRuntime.make(
|
|
40
|
+
SqlTransaction.layer
|
|
41
|
+
.pipe(Layer.provideMerge(sqliteLayerMemory), Layer.provideMerge(Reactivity.layer))
|
|
42
|
+
.pipe(Layer.orDie),
|
|
43
|
+
).runtimeEffect,
|
|
33
44
|
});
|
|
34
45
|
};
|
|
35
46
|
|
|
@@ -39,11 +50,11 @@ export const createServiceContext = async ({
|
|
|
39
50
|
return new MemorySignalManager(signalContext);
|
|
40
51
|
},
|
|
41
52
|
storage = createStorage({ type: StorageType.RAM }),
|
|
42
|
-
|
|
53
|
+
runtimeProps,
|
|
43
54
|
}: {
|
|
44
55
|
signalManagerFactory?: () => Promise<SignalManager>;
|
|
45
56
|
storage?: Storage;
|
|
46
|
-
|
|
57
|
+
runtimeProps?: ServiceContextRuntimeProps;
|
|
47
58
|
} = {}) => {
|
|
48
59
|
const signalManager = await signalManagerFactory();
|
|
49
60
|
const networkManager = new SwarmNetworkManager({
|
|
@@ -53,9 +64,15 @@ export const createServiceContext = async ({
|
|
|
53
64
|
const level = createTestLevel();
|
|
54
65
|
await level.open();
|
|
55
66
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
67
|
+
const runtime = ManagedRuntime.make(
|
|
68
|
+
SqlTransaction.layer
|
|
69
|
+
.pipe(Layer.provideMerge(sqliteLayerMemory), Layer.provideMerge(Reactivity.layer))
|
|
70
|
+
.pipe(Layer.orDie),
|
|
71
|
+
).runtimeEffect;
|
|
72
|
+
|
|
73
|
+
return new ServiceContext(storage, level, networkManager, signalManager, undefined, undefined, runtime, {
|
|
74
|
+
invitationConnectionDefaultProps: { teleport: { controlHeartbeatInterval: 200 } },
|
|
75
|
+
...runtimeProps,
|
|
59
76
|
});
|
|
60
77
|
};
|
|
61
78
|
|
|
@@ -95,7 +112,7 @@ export class TestBuilder {
|
|
|
95
112
|
|
|
96
113
|
export type TestPeerOpts = {
|
|
97
114
|
dataStore?: StorageType;
|
|
98
|
-
|
|
115
|
+
dataSpaceProps?: DataSpaceManagerRuntimeProps;
|
|
99
116
|
};
|
|
100
117
|
|
|
101
118
|
export type TestPeerProps = {
|
|
@@ -116,6 +133,11 @@ export type TestPeerProps = {
|
|
|
116
133
|
|
|
117
134
|
export class TestPeer {
|
|
118
135
|
private _props: TestPeerProps = {};
|
|
136
|
+
private readonly _runtime = ManagedRuntime.make(
|
|
137
|
+
SqlTransaction.layer
|
|
138
|
+
.pipe(Layer.provideMerge(sqliteLayerMemory), Layer.provideMerge(Reactivity.layer))
|
|
139
|
+
.pipe(Layer.orDie),
|
|
140
|
+
);
|
|
119
141
|
|
|
120
142
|
constructor(
|
|
121
143
|
private readonly _signalContext: MemorySignalManagerContext,
|
|
@@ -179,7 +201,10 @@ export class TestPeer {
|
|
|
179
201
|
}
|
|
180
202
|
|
|
181
203
|
get echoHost() {
|
|
182
|
-
return (this._props.echoHost ??= new EchoHost({
|
|
204
|
+
return (this._props.echoHost ??= new EchoHost({
|
|
205
|
+
kv: this.level,
|
|
206
|
+
runtime: this._runtime.runtimeEffect,
|
|
207
|
+
}));
|
|
183
208
|
}
|
|
184
209
|
|
|
185
210
|
get meshEchoReplicator() {
|
|
@@ -198,7 +223,7 @@ export class TestPeer {
|
|
|
198
223
|
edgeConnection: undefined,
|
|
199
224
|
meshReplicator: this.meshEchoReplicator,
|
|
200
225
|
echoEdgeReplicator: undefined,
|
|
201
|
-
|
|
226
|
+
runtimeProps: this._opts.dataSpaceProps,
|
|
202
227
|
}));
|
|
203
228
|
}
|
|
204
229
|
|
|
@@ -227,6 +252,7 @@ export class TestPeer {
|
|
|
227
252
|
async destroy(): Promise<void> {
|
|
228
253
|
await this.level.close();
|
|
229
254
|
await this.storage.reset();
|
|
255
|
+
await this._runtime.dispose();
|
|
230
256
|
}
|
|
231
257
|
}
|
|
232
258
|
|
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
// Copyright 2022 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import * as Reactivity from '@effect/experimental/Reactivity';
|
|
6
|
+
import type * as SqlClient from '@effect/sql/SqlClient';
|
|
7
|
+
import * as Effect from 'effect/Effect';
|
|
8
|
+
import * as Layer from 'effect/Layer';
|
|
9
|
+
import * as ManagedRuntime from 'effect/ManagedRuntime';
|
|
10
|
+
|
|
5
11
|
import { Trigger } from '@dxos/async';
|
|
6
12
|
import { DEFAULT_WORKER_BROADCAST_CHANNEL } from '@dxos/client-protocol';
|
|
7
13
|
import { type Config } from '@dxos/config';
|
|
@@ -16,6 +22,10 @@ import {
|
|
|
16
22
|
} from '@dxos/messaging';
|
|
17
23
|
import { RtcTransportProxyFactory } from '@dxos/network-manager';
|
|
18
24
|
import { type RpcPort } from '@dxos/rpc';
|
|
25
|
+
import * as OpfsWorker from '@dxos/sql-sqlite/OpfsWorker';
|
|
26
|
+
import * as SqlExport from '@dxos/sql-sqlite/SqlExport';
|
|
27
|
+
import * as SqliteClient from '@dxos/sql-sqlite/SqliteClient';
|
|
28
|
+
import * as SqlTransaction from '@dxos/sql-sqlite/SqlTransaction';
|
|
19
29
|
import { type MaybePromise } from '@dxos/util';
|
|
20
30
|
|
|
21
31
|
import { ClientServicesHost } from '../services';
|
|
@@ -23,10 +33,11 @@ import { ClientServicesHost } from '../services';
|
|
|
23
33
|
import { WorkerSession } from './worker-session';
|
|
24
34
|
|
|
25
35
|
// NOTE: Keep as RpcPorts to avoid dependency on @dxos/rpc-tunnel so we don't depend on browser-specific apis.
|
|
26
|
-
export type
|
|
36
|
+
export type CreateSessionProps = {
|
|
27
37
|
appPort: RpcPort;
|
|
28
38
|
systemPort: RpcPort;
|
|
29
39
|
shellPort?: RpcPort;
|
|
40
|
+
onClose?: () => Promise<void>;
|
|
30
41
|
};
|
|
31
42
|
|
|
32
43
|
export type WorkerRuntimeOptions = {
|
|
@@ -35,10 +46,20 @@ export type WorkerRuntimeOptions = {
|
|
|
35
46
|
acquireLock: () => Promise<void>;
|
|
36
47
|
releaseLock: () => void;
|
|
37
48
|
onStop?: () => Promise<void>;
|
|
49
|
+
/**
|
|
50
|
+
* @default true
|
|
51
|
+
*/
|
|
52
|
+
automaticallyConnectWebrtc?: boolean;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Optional SQLite layer for Effect. Defaults to LocalSqliteOpfsLayer.
|
|
56
|
+
* For testing in Node.js, use `sqliteLayerMemory` from `@dxos/sql-sqlite/platform`.
|
|
57
|
+
*/
|
|
58
|
+
sqliteLayer?: Layer.Layer<SqlClient.SqlClient | SqlExport.SqlExport, unknown>;
|
|
38
59
|
};
|
|
39
60
|
|
|
40
61
|
/**
|
|
41
|
-
* Runtime for the shared worker.
|
|
62
|
+
* Runtime for the shared and dedciated worker.
|
|
42
63
|
* Manages connections from proxies (in tabs).
|
|
43
64
|
* Tabs make requests to the `ClientServicesHost`, and provide a WebRTC gateway.
|
|
44
65
|
*/
|
|
@@ -52,11 +73,17 @@ export class WorkerRuntime {
|
|
|
52
73
|
private readonly _sessions = new Set<WorkerSession>();
|
|
53
74
|
private readonly _clientServices!: ClientServicesHost;
|
|
54
75
|
private readonly _channel: string;
|
|
76
|
+
private readonly _automaticallyConnectWebrtc: boolean;
|
|
77
|
+
private readonly _livenessLock = new WebLockWrapper(`@dxos/client-services/WorkerRuntime/${crypto.randomUUID()}`);
|
|
55
78
|
private _broadcastChannel?: BroadcastChannel;
|
|
56
79
|
private _sessionForNetworking?: WorkerSession; // TODO(burdon): Expose to client QueryStatusResponse.
|
|
57
80
|
private _config!: Config;
|
|
58
81
|
private _signalMetadataTags: any = { runtime: 'worker-runtime' };
|
|
59
82
|
private _signalTelemetryEnabled: boolean = false;
|
|
83
|
+
private _runtime!: ManagedRuntime.ManagedRuntime<
|
|
84
|
+
SqlTransaction.SqlTransaction | SqlClient.SqlClient | SqlExport.SqlExport,
|
|
85
|
+
never
|
|
86
|
+
>;
|
|
60
87
|
|
|
61
88
|
constructor({
|
|
62
89
|
channel = DEFAULT_WORKER_BROADCAST_CHANNEL,
|
|
@@ -64,26 +91,49 @@ export class WorkerRuntime {
|
|
|
64
91
|
acquireLock,
|
|
65
92
|
releaseLock,
|
|
66
93
|
onStop,
|
|
94
|
+
automaticallyConnectWebrtc = true,
|
|
95
|
+
sqliteLayer,
|
|
67
96
|
}: WorkerRuntimeOptions) {
|
|
68
97
|
this._configProvider = configProvider;
|
|
69
98
|
this._acquireLock = acquireLock;
|
|
70
99
|
this._releaseLock = releaseLock;
|
|
71
100
|
this._onStop = onStop;
|
|
72
101
|
this._channel = channel;
|
|
102
|
+
if (sqliteLayer) {
|
|
103
|
+
log.warn('Using testing SQLite layer');
|
|
104
|
+
}
|
|
105
|
+
this._runtime = ManagedRuntime.make(
|
|
106
|
+
SqlTransaction.layer
|
|
107
|
+
.pipe(Layer.provideMerge(sqliteLayer ?? LocalSqliteOpfsLayer), Layer.provideMerge(Reactivity.layer))
|
|
108
|
+
.pipe(Layer.orDie),
|
|
109
|
+
);
|
|
73
110
|
this._clientServices = new ClientServicesHost({
|
|
74
111
|
callbacks: {
|
|
75
112
|
onReset: async () => this.stop(),
|
|
76
113
|
},
|
|
114
|
+
runtime: this._runtime.runtimeEffect,
|
|
115
|
+
runtimeProps: {
|
|
116
|
+
// Auto-activate spaces that were previously active after leader changeover.
|
|
117
|
+
autoActivateSpaces: true,
|
|
118
|
+
},
|
|
77
119
|
});
|
|
120
|
+
this._automaticallyConnectWebrtc = automaticallyConnectWebrtc;
|
|
78
121
|
}
|
|
79
122
|
|
|
80
123
|
get host() {
|
|
81
124
|
return this._clientServices;
|
|
82
125
|
}
|
|
83
126
|
|
|
127
|
+
get livenessLockKey(): string {
|
|
128
|
+
return this._livenessLock.key;
|
|
129
|
+
}
|
|
130
|
+
|
|
84
131
|
async start(): Promise<void> {
|
|
85
132
|
log('starting...');
|
|
86
133
|
try {
|
|
134
|
+
void this._livenessLock.acquire();
|
|
135
|
+
|
|
136
|
+
// Steal the lock from the other worker.
|
|
87
137
|
this._broadcastChannel = new BroadcastChannel(this._channel);
|
|
88
138
|
this._broadcastChannel.postMessage({ action: 'stop' });
|
|
89
139
|
this._broadcastChannel.onmessage = async (event) => {
|
|
@@ -127,13 +177,15 @@ export class WorkerRuntime {
|
|
|
127
177
|
this._broadcastChannel?.close();
|
|
128
178
|
this._broadcastChannel = undefined;
|
|
129
179
|
await this._clientServices.close();
|
|
180
|
+
await this._runtime.dispose();
|
|
130
181
|
await this._onStop?.();
|
|
182
|
+
await this._livenessLock.release();
|
|
131
183
|
}
|
|
132
184
|
|
|
133
185
|
/**
|
|
134
186
|
* Create a new session.
|
|
135
187
|
*/
|
|
136
|
-
async createSession({ appPort, systemPort, shellPort }:
|
|
188
|
+
async createSession({ appPort, systemPort, shellPort, onClose }: CreateSessionProps): Promise<WorkerSession> {
|
|
137
189
|
const session = new WorkerSession({
|
|
138
190
|
serviceHost: this._clientServices,
|
|
139
191
|
appPort,
|
|
@@ -149,8 +201,11 @@ export class WorkerRuntime {
|
|
|
149
201
|
// Terminate the worker when all sessions are closed.
|
|
150
202
|
await this.stop();
|
|
151
203
|
} else {
|
|
152
|
-
this.
|
|
204
|
+
if (this._automaticallyConnectWebrtc) {
|
|
205
|
+
this._reconnectWebrtc();
|
|
206
|
+
}
|
|
153
207
|
}
|
|
208
|
+
await onClose?.();
|
|
154
209
|
});
|
|
155
210
|
|
|
156
211
|
await session.open();
|
|
@@ -166,7 +221,24 @@ export class WorkerRuntime {
|
|
|
166
221
|
this._signalMetadataTags.origin = session.origin;
|
|
167
222
|
this._sessions.add(session);
|
|
168
223
|
|
|
169
|
-
this.
|
|
224
|
+
if (this._automaticallyConnectWebrtc) {
|
|
225
|
+
this._reconnectWebrtc();
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return session;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Connects the WebRTC bridge to the specified session.
|
|
233
|
+
* If no session is provided, disconnects the WebRTC bridge.
|
|
234
|
+
*
|
|
235
|
+
* Called automatically if `automaticallyConnectWebrtc` is true.
|
|
236
|
+
*
|
|
237
|
+
* @param session The session to connect the WebRTC bridge to.
|
|
238
|
+
*/
|
|
239
|
+
connectWebrtcBridge(session: WorkerSession | undefined): void {
|
|
240
|
+
this._sessionForNetworking = session;
|
|
241
|
+
this._transportFactory.setBridgeService(session?.bridgeService);
|
|
170
242
|
}
|
|
171
243
|
|
|
172
244
|
/**
|
|
@@ -184,12 +256,78 @@ export class WorkerRuntime {
|
|
|
184
256
|
// Select existing session.
|
|
185
257
|
if (!this._sessionForNetworking) {
|
|
186
258
|
const selected = Array.from(this._sessions).find((session) => session.bridgeService);
|
|
187
|
-
|
|
188
|
-
this._sessionForNetworking = selected;
|
|
189
|
-
this._transportFactory.setBridgeService(selected.bridgeService);
|
|
190
|
-
} else {
|
|
191
|
-
this._transportFactory.setBridgeService(undefined);
|
|
192
|
-
}
|
|
259
|
+
this.connectWebrtcBridge(selected);
|
|
193
260
|
}
|
|
194
261
|
}
|
|
195
262
|
}
|
|
263
|
+
|
|
264
|
+
const DB_NAME = 'DXOS';
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* SqlExport layer that wraps SqliteClient to provide export functionality.
|
|
268
|
+
*/
|
|
269
|
+
const SqlExportLayer: Layer.Layer<SqlExport.SqlExport, never, SqliteClient.SqliteClient> = Layer.effect(
|
|
270
|
+
SqlExport.SqlExport,
|
|
271
|
+
Effect.gen(function* () {
|
|
272
|
+
const sql = yield* SqliteClient.SqliteClient;
|
|
273
|
+
return {
|
|
274
|
+
export: sql.export,
|
|
275
|
+
} satisfies SqlExport.Service;
|
|
276
|
+
}),
|
|
277
|
+
);
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Local SQLite layer for the worker.
|
|
281
|
+
* Uses OPFS sync API as an FS backend.
|
|
282
|
+
* Does NOT spawn a new worker.
|
|
283
|
+
* NOTE: Only usable within a worker.
|
|
284
|
+
* TODO(mykola): This does not work right now. Fix.
|
|
285
|
+
*/
|
|
286
|
+
const LocalSqliteOpfsLayer = Layer.unwrapScoped(
|
|
287
|
+
Effect.gen(function* () {
|
|
288
|
+
const { port1: clientPort, port2: serverPort } = new MessageChannel();
|
|
289
|
+
clientPort.start();
|
|
290
|
+
serverPort.start();
|
|
291
|
+
yield* Effect.addFinalizer(() =>
|
|
292
|
+
Effect.sync(() => {
|
|
293
|
+
clientPort.close();
|
|
294
|
+
serverPort.close();
|
|
295
|
+
}),
|
|
296
|
+
);
|
|
297
|
+
|
|
298
|
+
yield* Effect.forkScoped(OpfsWorker.run({ port: serverPort, dbName: DB_NAME }));
|
|
299
|
+
return SqlExportLayer.pipe(Layer.provideMerge(SqliteClient.layer({ worker: Effect.succeed(clientPort) })));
|
|
300
|
+
}),
|
|
301
|
+
);
|
|
302
|
+
|
|
303
|
+
// TODO(wittjosiah): Factor out to a separate module.
|
|
304
|
+
class WebLockWrapper {
|
|
305
|
+
readonly #key: string;
|
|
306
|
+
#release?: () => void;
|
|
307
|
+
|
|
308
|
+
constructor(key: string) {
|
|
309
|
+
this.#key = key;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
get key(): string {
|
|
313
|
+
return this.#key;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
acquire(options: LockOptions = {}) {
|
|
317
|
+
return navigator.locks.request(this.#key, options, async () => {
|
|
318
|
+
await new Promise<void>((resolve) => {
|
|
319
|
+
this.#release = resolve;
|
|
320
|
+
}); // Blocks for the duration of the worker's lifetime.
|
|
321
|
+
this.#release = undefined;
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
release() {
|
|
326
|
+
this.#release?.();
|
|
327
|
+
this.#release = undefined;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
[Symbol.dispose]() {
|
|
331
|
+
this.release();
|
|
332
|
+
}
|
|
333
|
+
}
|
|
@@ -15,9 +15,9 @@ import { type BridgeService } from '@dxos/protocols/proto/dxos/mesh/bridge';
|
|
|
15
15
|
import { type ProtoRpcPeer, type RpcPort, createProtoRpcPeer } from '@dxos/rpc';
|
|
16
16
|
import { Callback, type MaybePromise } from '@dxos/util';
|
|
17
17
|
|
|
18
|
-
import { ClientRpcServer, type
|
|
18
|
+
import { ClientRpcServer, type ClientRpcServerProps, type ClientServicesHost } from '../services';
|
|
19
19
|
|
|
20
|
-
export type
|
|
20
|
+
export type WorkerSessionProps = {
|
|
21
21
|
serviceHost: ClientServicesHost;
|
|
22
22
|
systemPort: RpcPort;
|
|
23
23
|
appPort: RpcPort;
|
|
@@ -50,11 +50,11 @@ export class WorkerSession {
|
|
|
50
50
|
|
|
51
51
|
public bridgeService?: BridgeService;
|
|
52
52
|
|
|
53
|
-
constructor({ serviceHost, systemPort, appPort, shellPort, readySignal }:
|
|
53
|
+
constructor({ serviceHost, systemPort, appPort, shellPort, readySignal }: WorkerSessionProps) {
|
|
54
54
|
invariant(serviceHost);
|
|
55
55
|
this._serviceHost = serviceHost;
|
|
56
56
|
|
|
57
|
-
const middleware: Pick<
|
|
57
|
+
const middleware: Pick<ClientRpcServerProps, 'handleCall' | 'handleStream'> = {
|
|
58
58
|
handleCall: async (method, params, handler) => {
|
|
59
59
|
const error = await readySignal.wait({ timeout: PROXY_CONNECTION_TIMEOUT });
|
|
60
60
|
if (error) {
|
|
@@ -119,7 +119,7 @@ export class WorkerSession {
|
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
async open(): Promise<void> {
|
|
122
|
-
log
|
|
122
|
+
log('opening...');
|
|
123
123
|
await Promise.all([this._clientRpc.open(), this._iframeRpc.open(), this._maybeOpenShell()]);
|
|
124
124
|
|
|
125
125
|
// Wait until the worker's RPC service has started.
|
|
@@ -130,11 +130,11 @@ export class WorkerSession {
|
|
|
130
130
|
void this._afterLockReleases(this.lockKey, () => this.close());
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
-
log
|
|
133
|
+
log('opened');
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
async close(): Promise<void> {
|
|
137
|
-
log.
|
|
137
|
+
log.debug('closing...');
|
|
138
138
|
try {
|
|
139
139
|
await this.onClose.callIfSet();
|
|
140
140
|
} catch (err: any) {
|
|
@@ -142,7 +142,7 @@ export class WorkerSession {
|
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
await Promise.all([this._clientRpc.close(), this._iframeRpc.close()]);
|
|
145
|
-
log.
|
|
145
|
+
log.debug('closed');
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
private async _maybeOpenShell(): Promise<void> {
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const DXOS_VERSION = "0.8.4-main.
|
|
1
|
+
export const DXOS_VERSION = "0.8.4-main.c85a9c8dae";
|