@dxos/client-services 0.10.0 → 0.11.0
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/chunk-client-services-layer.mjs +11425 -0
- package/dist/lib/chunk-client-services-layer.mjs.map +1 -0
- package/dist/lib/chunk-decorate.mjs +9 -0
- package/dist/lib/index.mjs +731 -0
- package/dist/lib/index.mjs.map +1 -0
- package/dist/lib/packlets/diagnostics/browser-diagnostics-broadcast.mjs +72 -0
- package/dist/lib/packlets/diagnostics/browser-diagnostics-broadcast.mjs.map +1 -0
- package/dist/lib/packlets/diagnostics/diagnostics-broadcast.mjs +14 -0
- package/dist/lib/packlets/diagnostics/diagnostics-broadcast.mjs.map +1 -0
- package/dist/lib/packlets/locks/browser.mjs +105 -0
- package/dist/lib/packlets/locks/browser.mjs.map +1 -0
- package/dist/lib/packlets/locks/node.mjs +53 -0
- package/dist/lib/packlets/locks/node.mjs.map +1 -0
- package/dist/lib/testing.mjs +570 -0
- package/dist/lib/testing.mjs.map +1 -0
- package/dist/types/src/index.d.ts +2 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/packlets/agents/edge-agent-manager.d.ts +21 -4
- package/dist/types/src/packlets/agents/edge-agent-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/agents/edge-agent-service.d.ts +8 -7
- package/dist/types/src/packlets/agents/edge-agent-service.d.ts.map +1 -1
- package/dist/types/src/packlets/devices/devices-service.d.ts +7 -5
- package/dist/types/src/packlets/devices/devices-service.d.ts.map +1 -1
- package/dist/types/src/packlets/devtools/devtools.d.ts +30 -29
- package/dist/types/src/packlets/devtools/devtools.d.ts.map +1 -1
- package/dist/types/src/packlets/devtools/feeds.d.ts +1 -1
- package/dist/types/src/packlets/devtools/feeds.d.ts.map +1 -1
- package/dist/types/src/packlets/devtools/network.d.ts +2 -1
- package/dist/types/src/packlets/devtools/network.d.ts.map +1 -1
- package/dist/types/src/packlets/devtools/spaces.d.ts.map +1 -1
- package/dist/types/src/packlets/diagnostics/diagnostics-broadcast.d.ts +2 -2
- package/dist/types/src/packlets/diagnostics/diagnostics-broadcast.d.ts.map +1 -1
- package/dist/types/src/packlets/diagnostics/diagnostics-collector.d.ts.map +1 -1
- package/dist/types/src/packlets/diagnostics/diagnostics.d.ts +1 -8
- package/dist/types/src/packlets/diagnostics/diagnostics.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/authenticator.d.ts +1 -1
- package/dist/types/src/packlets/identity/authenticator.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/contacts-service.d.ts +9 -6
- package/dist/types/src/packlets/identity/contacts-service.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity-manager.d.ts +32 -3
- package/dist/types/src/packlets/identity/identity-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts +23 -4
- package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity-service.d.ts +15 -20
- package/dist/types/src/packlets/identity/identity-service.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/edge-invitation-handler.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitations-handler.d.ts +17 -0
- package/dist/types/src/packlets/invitations/invitations-handler.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitations-manager.d.ts +25 -4
- package/dist/types/src/packlets/invitations/invitations-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitations-service.d.ts +11 -11
- package/dist/types/src/packlets/invitations/invitations-service.d.ts.map +1 -1
- package/dist/types/src/packlets/logging/logging-service.d.ts +14 -12
- package/dist/types/src/packlets/logging/logging-service.d.ts.map +1 -1
- package/dist/types/src/packlets/metadata/index.d.ts +3 -0
- package/dist/types/src/packlets/metadata/index.d.ts.map +1 -0
- package/dist/types/src/packlets/metadata/metadata-store.d.ts +107 -0
- package/dist/types/src/packlets/metadata/metadata-store.d.ts.map +1 -0
- package/dist/types/src/packlets/metadata/metadata-store.test.d.ts +2 -0
- package/dist/types/src/packlets/metadata/metadata-store.test.d.ts.map +1 -0
- package/dist/types/src/packlets/metadata/sqlite-metadata-store.d.ts +65 -0
- package/dist/types/src/packlets/metadata/sqlite-metadata-store.d.ts.map +1 -0
- package/dist/types/src/packlets/network/network-service.d.ts +15 -14
- package/dist/types/src/packlets/network/network-service.d.ts.map +1 -1
- package/dist/types/src/packlets/pipeline/codec.d.ts +11 -0
- package/dist/types/src/packlets/pipeline/codec.d.ts.map +1 -0
- package/dist/types/src/packlets/pipeline/feeds.d.ts +7 -0
- package/dist/types/src/packlets/pipeline/feeds.d.ts.map +1 -0
- package/dist/types/src/packlets/pipeline/index.d.ts +5 -0
- package/dist/types/src/packlets/pipeline/index.d.ts.map +1 -0
- package/dist/types/src/packlets/pipeline/message-selector.d.ts +11 -0
- package/dist/types/src/packlets/pipeline/message-selector.d.ts.map +1 -0
- package/dist/types/src/packlets/pipeline/pipeline-stress.test.d.ts +2 -0
- package/dist/types/src/packlets/pipeline/pipeline-stress.test.d.ts.map +1 -0
- package/dist/types/src/packlets/pipeline/pipeline.d.ts +131 -0
- package/dist/types/src/packlets/pipeline/pipeline.d.ts.map +1 -0
- package/dist/types/src/packlets/pipeline/pipeline.test.d.ts +2 -0
- package/dist/types/src/packlets/pipeline/pipeline.test.d.ts.map +1 -0
- package/dist/types/src/packlets/pipeline/testing/index.d.ts +2 -0
- package/dist/types/src/packlets/pipeline/testing/index.d.ts.map +1 -0
- package/dist/types/src/packlets/pipeline/testing/test-feed-builder.d.ts +9 -0
- package/dist/types/src/packlets/pipeline/testing/test-feed-builder.d.ts.map +1 -0
- package/dist/types/src/packlets/pipeline/timeframe-clock.d.ts +31 -0
- package/dist/types/src/packlets/pipeline/timeframe-clock.d.ts.map +1 -0
- package/dist/types/src/packlets/services/client-services-layer.d.ts +21 -0
- package/dist/types/src/packlets/services/client-services-layer.d.ts.map +1 -0
- package/dist/types/src/packlets/services/cross-device-space-synchronizer.d.ts +28 -0
- package/dist/types/src/packlets/services/cross-device-space-synchronizer.d.ts.map +1 -0
- package/dist/types/src/packlets/services/effect-rpc.test.d.ts +2 -0
- package/dist/types/src/packlets/services/effect-rpc.test.d.ts.map +1 -0
- package/dist/types/src/packlets/services/feed-syncer.d.ts +22 -2
- package/dist/types/src/packlets/services/feed-syncer.d.ts.map +1 -1
- package/dist/types/src/packlets/services/index.d.ts +2 -2
- package/dist/types/src/packlets/services/index.d.ts.map +1 -1
- package/dist/types/src/packlets/services/platform.d.ts.map +1 -1
- package/dist/types/src/packlets/services/service-context.d.ts +38 -57
- package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
- package/dist/types/src/packlets/services/service-host.d.ts +82 -31
- package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
- package/dist/types/src/packlets/services/sqlite-storage.d.ts +29 -0
- package/dist/types/src/packlets/services/sqlite-storage.d.ts.map +1 -1
- package/dist/types/src/packlets/services/sqlite-storage.test.d.ts +2 -0
- package/dist/types/src/packlets/services/sqlite-storage.test.d.ts.map +1 -0
- package/dist/types/src/packlets/space/admission-discovery-extension.d.ts +30 -0
- package/dist/types/src/packlets/space/admission-discovery-extension.d.ts.map +1 -0
- package/dist/types/src/packlets/space/auth.d.ts +24 -0
- package/dist/types/src/packlets/space/auth.d.ts.map +1 -0
- package/dist/types/src/packlets/space/control-pipeline.d.ts +46 -0
- package/dist/types/src/packlets/space/control-pipeline.d.ts.map +1 -0
- package/dist/types/src/packlets/space/control-pipeline.test.d.ts +2 -0
- package/dist/types/src/packlets/space/control-pipeline.test.d.ts.map +1 -0
- package/dist/types/src/packlets/space/index.d.ts +6 -0
- package/dist/types/src/packlets/space/index.d.ts.map +1 -0
- package/dist/types/src/packlets/space/replication.browser.test.d.ts +2 -0
- package/dist/types/src/packlets/space/replication.browser.test.d.ts.map +1 -0
- package/dist/types/src/packlets/space/space-manager.browser.test.d.ts +2 -0
- package/dist/types/src/packlets/space/space-manager.browser.test.d.ts.map +1 -0
- package/dist/types/src/packlets/space/space-manager.d.ts +72 -0
- package/dist/types/src/packlets/space/space-manager.d.ts.map +1 -0
- package/dist/types/src/packlets/space/space-protocol.browser.test.d.ts +2 -0
- package/dist/types/src/packlets/space/space-protocol.browser.test.d.ts.map +1 -0
- package/dist/types/src/packlets/space/space-protocol.d.ts +99 -0
- package/dist/types/src/packlets/space/space-protocol.d.ts.map +1 -0
- package/dist/types/src/packlets/space/space-protocol.test.d.ts +2 -0
- package/dist/types/src/packlets/space/space-protocol.test.d.ts.map +1 -0
- package/dist/types/src/packlets/space/space.d.ts +65 -0
- package/dist/types/src/packlets/space/space.d.ts.map +1 -0
- package/dist/types/src/packlets/space/space.test.d.ts +2 -0
- package/dist/types/src/packlets/space/space.test.d.ts.map +1 -0
- package/dist/types/src/packlets/space/testing/change-metadata.d.ts +8 -0
- package/dist/types/src/packlets/space/testing/change-metadata.d.ts.map +1 -0
- package/dist/types/src/packlets/space/testing/index.d.ts +4 -0
- package/dist/types/src/packlets/space/testing/index.d.ts.map +1 -0
- package/dist/types/src/packlets/space/testing/test-agent-builder.d.ts +62 -0
- package/dist/types/src/packlets/space/testing/test-agent-builder.d.ts.map +1 -0
- package/dist/types/src/packlets/space-export/serialized-space-reader.d.ts +1 -1
- package/dist/types/src/packlets/space-export/serialized-space-reader.d.ts.map +1 -1
- package/dist/types/src/packlets/space-export/serialized-space-writer.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/data-space-manager.d.ts +40 -7
- package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/data-space.d.ts +3 -1
- package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/genesis.d.ts +1 -1
- package/dist/types/src/packlets/spaces/genesis.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/spaces-service.d.ts +25 -23
- package/dist/types/src/packlets/spaces/spaces-service.d.ts.map +1 -1
- package/dist/types/src/packlets/storage/level.d.ts.map +1 -1
- package/dist/types/src/packlets/system/system-service.d.ts +18 -18
- package/dist/types/src/packlets/system/system-service.d.ts.map +1 -1
- package/dist/types/src/packlets/testing/invitation-utils.d.ts +1 -1
- package/dist/types/src/packlets/testing/invitation-utils.d.ts.map +1 -1
- package/dist/types/src/packlets/testing/test-builder.d.ts +7 -6
- package/dist/types/src/packlets/testing/test-builder.d.ts.map +1 -1
- package/dist/types/src/packlets/worker/worker-runtime.d.ts +41 -58
- package/dist/types/src/packlets/worker/worker-runtime.d.ts.map +1 -1
- package/dist/types/src/packlets/worker/worker-session.d.ts +21 -8
- package/dist/types/src/packlets/worker/worker-session.d.ts.map +1 -1
- package/dist/types/src/testing/index.d.ts +1 -0
- package/dist/types/src/testing/index.d.ts.map +1 -1
- package/dist/types/src/version.d.ts +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +52 -48
- package/src/index.ts +2 -0
- package/src/packlets/agents/edge-agent-manager.ts +56 -15
- package/src/packlets/agents/edge-agent-service.ts +25 -15
- package/src/packlets/devices/devices-service.test.ts +20 -19
- package/src/packlets/devices/devices-service.ts +17 -17
- package/src/packlets/devtools/devtools.ts +133 -75
- package/src/packlets/devtools/feeds.ts +2 -1
- package/src/packlets/devtools/network.ts +42 -12
- package/src/packlets/devtools/spaces.ts +1 -1
- package/src/packlets/diagnostics/diagnostics-broadcast.ts +4 -2
- package/src/packlets/diagnostics/diagnostics-collector.ts +5 -18
- package/src/packlets/diagnostics/diagnostics.ts +0 -11
- package/src/packlets/identity/authenticator.ts +2 -1
- package/src/packlets/identity/contacts-service.ts +46 -37
- package/src/packlets/identity/identity-manager.test.ts +3 -1
- package/src/packlets/identity/identity-manager.ts +73 -5
- package/src/packlets/identity/identity-recovery-manager.ts +56 -7
- package/src/packlets/identity/identity-service.test.ts +27 -18
- package/src/packlets/identity/identity-service.ts +114 -71
- package/src/packlets/identity/identity.test.ts +4 -9
- package/src/packlets/identity/identity.ts +1 -2
- package/src/packlets/invitations/edge-invitation-handler.ts +0 -1
- package/src/packlets/invitations/invitations-handler.ts +39 -3
- package/src/packlets/invitations/invitations-manager.ts +52 -4
- package/src/packlets/invitations/invitations-service.ts +54 -28
- package/src/packlets/logging/logging-service.ts +41 -29
- package/src/packlets/logging/logging.test.ts +28 -15
- package/src/packlets/metadata/index.ts +6 -0
- package/src/packlets/metadata/metadata-store.test.ts +49 -0
- package/src/packlets/metadata/metadata-store.ts +446 -0
- package/src/packlets/metadata/sqlite-metadata-store.ts +409 -0
- package/src/packlets/network/network-service.test.ts +19 -12
- package/src/packlets/network/network-service.ts +96 -29
- package/src/packlets/pipeline/codec.ts +18 -0
- package/src/packlets/pipeline/feeds.ts +22 -0
- package/src/packlets/pipeline/index.ts +8 -0
- package/src/packlets/pipeline/message-selector.ts +35 -0
- package/src/packlets/pipeline/pipeline-stress.test.ts +230 -0
- package/src/packlets/pipeline/pipeline.test.ts +140 -0
- package/src/packlets/pipeline/pipeline.ts +439 -0
- package/src/packlets/pipeline/testing/index.ts +5 -0
- package/src/packlets/pipeline/testing/test-feed-builder.ts +19 -0
- package/src/packlets/pipeline/timeframe-clock.ts +81 -0
- package/src/packlets/services/client-services-layer.ts +186 -0
- package/src/packlets/services/cross-device-space-synchronizer.ts +132 -0
- package/src/packlets/services/effect-rpc.test.ts +314 -0
- package/src/packlets/services/feed-syncer.ts +57 -3
- package/src/packlets/services/index.ts +2 -2
- package/src/packlets/services/platform.ts +0 -6
- package/src/packlets/services/service-context.ts +219 -522
- package/src/packlets/services/service-host.test.ts +34 -11
- package/src/packlets/services/service-host.ts +693 -213
- package/src/packlets/services/spec.md +106 -0
- package/src/packlets/services/sqlite-storage.test.ts +48 -0
- package/src/packlets/services/sqlite-storage.ts +117 -20
- package/src/packlets/space/admission-discovery-extension.ts +91 -0
- package/src/packlets/space/auth.ts +92 -0
- package/src/packlets/space/control-pipeline.test.ts +165 -0
- package/src/packlets/space/control-pipeline.ts +229 -0
- package/src/packlets/space/index.ts +9 -0
- package/src/packlets/space/replication.browser.test.ts +58 -0
- package/src/packlets/space/space-manager.browser.test.ts +40 -0
- package/src/packlets/space/space-manager.ts +224 -0
- package/src/packlets/space/space-protocol.browser.test.ts +129 -0
- package/src/packlets/space/space-protocol.test.ts +158 -0
- package/src/packlets/space/space-protocol.ts +308 -0
- package/src/packlets/space/space.test.ts +181 -0
- package/src/packlets/space/space.ts +196 -0
- package/src/packlets/space/testing/change-metadata.ts +27 -0
- package/src/packlets/space/testing/index.ts +7 -0
- package/src/packlets/space/testing/test-agent-builder.ts +252 -0
- package/src/packlets/space-export/serialized-space-reader.ts +3 -1
- package/src/packlets/space-export/serialized-space-writer.ts +53 -30
- package/src/packlets/space-export/space-archive.test.ts +30 -0
- package/src/packlets/spaces/data-space-manager.test.ts +1 -1
- package/src/packlets/spaces/data-space-manager.ts +148 -33
- package/src/packlets/spaces/data-space.ts +29 -18
- package/src/packlets/spaces/edge-feed-replicator.test.ts +1 -1
- package/src/packlets/spaces/genesis.ts +1 -1
- package/src/packlets/spaces/spaces-service.test.ts +35 -22
- package/src/packlets/spaces/spaces-service.ts +259 -180
- package/src/packlets/storage/level.ts +3 -1
- package/src/packlets/system/system-service.test.ts +31 -13
- package/src/packlets/system/system-service.ts +65 -37
- package/src/packlets/testing/invitation-utils.ts +3 -3
- package/src/packlets/testing/test-builder.ts +35 -20
- package/src/packlets/worker/worker-runtime.ts +222 -260
- package/src/packlets/worker/worker-session.ts +108 -91
- package/src/testing/index.ts +1 -0
- package/src/version.ts +1 -1
- package/dist/lib/browser/chunk-QCWEHHJW.mjs +0 -24
- package/dist/lib/browser/chunk-QCWEHHJW.mjs.map +0 -7
- package/dist/lib/browser/chunk-XJRPB3GA.mjs +0 -22
- package/dist/lib/browser/chunk-XJRPB3GA.mjs.map +0 -7
- package/dist/lib/browser/chunk-XU5R2BMF.mjs +0 -8837
- package/dist/lib/browser/chunk-XU5R2BMF.mjs.map +0 -7
- package/dist/lib/browser/index.mjs +0 -876
- package/dist/lib/browser/index.mjs.map +0 -7
- package/dist/lib/browser/meta.json +0 -1
- package/dist/lib/browser/packlets/diagnostics/browser-diagnostics-broadcast.mjs +0 -88
- package/dist/lib/browser/packlets/diagnostics/browser-diagnostics-broadcast.mjs.map +0 -7
- package/dist/lib/browser/packlets/diagnostics/diagnostics-broadcast.mjs +0 -11
- package/dist/lib/browser/packlets/diagnostics/diagnostics-broadcast.mjs.map +0 -7
- package/dist/lib/browser/packlets/locks/browser.mjs +0 -86
- package/dist/lib/browser/packlets/locks/browser.mjs.map +0 -7
- package/dist/lib/browser/packlets/locks/node.mjs +0 -48
- package/dist/lib/browser/packlets/locks/node.mjs.map +0 -7
- package/dist/lib/browser/testing/index.mjs +0 -436
- package/dist/lib/browser/testing/index.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-2DT3MZRL.mjs +0 -22
- package/dist/lib/node-esm/chunk-2DT3MZRL.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-2SZHAWBN.mjs +0 -24
- package/dist/lib/node-esm/chunk-2SZHAWBN.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-H5YTUD35.mjs +0 -8837
- package/dist/lib/node-esm/chunk-H5YTUD35.mjs.map +0 -7
- package/dist/lib/node-esm/index.mjs +0 -876
- package/dist/lib/node-esm/index.mjs.map +0 -7
- package/dist/lib/node-esm/meta.json +0 -1
- package/dist/lib/node-esm/packlets/diagnostics/browser-diagnostics-broadcast.mjs +0 -88
- package/dist/lib/node-esm/packlets/diagnostics/browser-diagnostics-broadcast.mjs.map +0 -7
- package/dist/lib/node-esm/packlets/diagnostics/diagnostics-broadcast.mjs +0 -11
- package/dist/lib/node-esm/packlets/diagnostics/diagnostics-broadcast.mjs.map +0 -7
- package/dist/lib/node-esm/packlets/locks/browser.mjs +0 -86
- package/dist/lib/node-esm/packlets/locks/browser.mjs.map +0 -7
- package/dist/lib/node-esm/packlets/locks/node.mjs +0 -48
- package/dist/lib/node-esm/packlets/locks/node.mjs.map +0 -7
- package/dist/lib/node-esm/testing/index.mjs +0 -436
- package/dist/lib/node-esm/testing/index.mjs.map +0 -7
- package/dist/types/src/packlets/services/client-rpc-server.d.ts +0 -24
- package/dist/types/src/packlets/services/client-rpc-server.d.ts.map +0 -1
- package/dist/types/src/packlets/services/service-registry.d.ts +0 -15
- package/dist/types/src/packlets/services/service-registry.d.ts.map +0 -1
- package/dist/types/src/packlets/services/service-registry.test.d.ts +0 -2
- package/dist/types/src/packlets/services/service-registry.test.d.ts.map +0 -1
- package/dist/types/src/testing/setup.d.ts +0 -3
- package/dist/types/src/testing/setup.d.ts.map +0 -1
- package/src/packlets/services/client-rpc-server.ts +0 -111
- package/src/packlets/services/service-registry.test.ts +0 -78
- package/src/packlets/services/service-registry.ts +0 -36
- package/src/testing/setup.ts +0 -11
|
@@ -3,67 +3,72 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import * as SqlClient from '@effect/sql/SqlClient';
|
|
6
|
+
import type * as SqlError from '@effect/sql/SqlError';
|
|
7
|
+
import * as EffectContext from 'effect/Context';
|
|
6
8
|
import * as Effect from 'effect/Effect';
|
|
9
|
+
import * as Layer from 'effect/Layer';
|
|
7
10
|
|
|
8
|
-
import { Mutex, Trigger } from '@dxos/async';
|
|
9
|
-
import { Context, Resource } from '@dxos/context';
|
|
10
|
-
import { type CredentialProcessor, getCredentialAssertion } from '@dxos/credentials';
|
|
11
|
-
import { failUndefined, warnAfterTimeout } from '@dxos/debug';
|
|
12
11
|
import {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
SpaceManager,
|
|
19
|
-
SqliteMetadataStore,
|
|
20
|
-
runSqliteHealthCheck,
|
|
21
|
-
valueEncoding,
|
|
12
|
+
EchoEdgeReplicatorLayer,
|
|
13
|
+
EchoEdgeSubductionReplicatorLayer,
|
|
14
|
+
EchoHostLayer,
|
|
15
|
+
EchoHostService,
|
|
16
|
+
MeshEchoReplicatorLayer,
|
|
22
17
|
} from '@dxos/echo-host';
|
|
23
|
-
import {
|
|
24
|
-
|
|
18
|
+
import {
|
|
19
|
+
type EdgeConnection,
|
|
20
|
+
EdgeConnectionService,
|
|
21
|
+
type EdgeHttpClient,
|
|
22
|
+
EdgeHttpClientService,
|
|
23
|
+
} from '@dxos/edge-client';
|
|
25
24
|
import { RuntimeProvider } from '@dxos/effect';
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
import { log } from '@dxos/log';
|
|
31
|
-
import { type SignalManager } from '@dxos/messaging';
|
|
32
|
-
import { type SwarmNetworkManager } from '@dxos/network-manager';
|
|
33
|
-
import { InvalidStorageVersionError, STORAGE_VERSION } from '@dxos/protocols';
|
|
25
|
+
import { FeedFactoryLayer, FeedStoreLayer, FeedStoreService } from '@dxos/feed-store';
|
|
26
|
+
import { KeyringApiService, SqliteKeyring, SqliteKeyringLayer } from '@dxos/keyring';
|
|
27
|
+
import { SignalManagerService } from '@dxos/messaging';
|
|
28
|
+
import { SwarmNetworkManagerService } from '@dxos/network-manager';
|
|
34
29
|
import { FeedProtocol } from '@dxos/protocols';
|
|
35
|
-
import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
|
|
36
30
|
import { type Runtime } from '@dxos/protocols/proto/dxos/config';
|
|
37
|
-
import type { FeedMessage } from '@dxos/protocols/proto/dxos/echo/feed';
|
|
38
|
-
import { type Credential, type ProfileDocument } from '@dxos/protocols/proto/dxos/halo/credentials';
|
|
39
31
|
import { SqlTransaction } from '@dxos/sql-sqlite';
|
|
40
|
-
import { SqliteBlobStore } from '@dxos/teleport-extension-object-sync';
|
|
41
|
-
import { trace as Trace } from '@dxos/tracing';
|
|
42
|
-
import { safeInstanceof } from '@dxos/util';
|
|
43
|
-
|
|
44
|
-
// SqlTransaction.SqlTransaction is the Tag class exported from the SqlTransaction namespace.
|
|
45
|
-
type SqlTransactionTag = SqlTransaction.SqlTransaction;
|
|
32
|
+
import { BlobStoreApiService, SqliteBlobStore, SqliteBlobStoreLayer } from '@dxos/teleport-extension-object-sync';
|
|
46
33
|
|
|
47
|
-
import {
|
|
34
|
+
import { EdgeAgentManagerLayer, EdgeAgentManagerService } from '../agents';
|
|
48
35
|
import {
|
|
49
|
-
|
|
50
|
-
type Identity,
|
|
51
|
-
IdentityManager,
|
|
36
|
+
IdentityManagerLayer,
|
|
52
37
|
type IdentityManagerProps,
|
|
53
|
-
|
|
38
|
+
IdentityManagerService,
|
|
39
|
+
IdentityProviderService,
|
|
40
|
+
identityProviderFromManager,
|
|
54
41
|
} from '../identity';
|
|
55
|
-
import { EdgeIdentityRecoveryManager } from '../identity/identity-recovery-manager';
|
|
56
42
|
import {
|
|
57
|
-
|
|
43
|
+
EdgeIdentityRecoveryManagerLayer,
|
|
44
|
+
EdgeIdentityRecoveryManagerService,
|
|
45
|
+
} from '../identity/identity-recovery-manager';
|
|
46
|
+
import {
|
|
58
47
|
type InvitationConnectionProps,
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
48
|
+
InvitationsHandlerLayer,
|
|
49
|
+
InvitationsHandlerService,
|
|
50
|
+
InvitationsManagerLayer,
|
|
51
|
+
InvitationsManagerService,
|
|
63
52
|
} from '../invitations';
|
|
64
|
-
import {
|
|
65
|
-
import {
|
|
66
|
-
import {
|
|
53
|
+
import { IMetadataStoreService, SqliteMetadataStore, SqliteMetadataStoreLayer } from '../metadata';
|
|
54
|
+
import { valueEncoding } from '../pipeline';
|
|
55
|
+
import { SpaceManagerLayer, SpaceManagerService } from '../space';
|
|
56
|
+
import {
|
|
57
|
+
DataSpaceManagerLayer,
|
|
58
|
+
type DataSpaceManagerRuntimeProps,
|
|
59
|
+
DataSpaceManagerService,
|
|
60
|
+
SigningContextProviderLayer,
|
|
61
|
+
SigningContextProviderService,
|
|
62
|
+
} from '../spaces';
|
|
63
|
+
import {
|
|
64
|
+
CrossDeviceSpaceSynchronizerLayer,
|
|
65
|
+
CrossDeviceSpaceSynchronizerService,
|
|
66
|
+
} from './cross-device-space-synchronizer';
|
|
67
|
+
import { FeedSyncerLayer } from './feed-syncer';
|
|
68
|
+
import { FeedStorageDirectoryLayer, SqliteStorage, SqliteStorageLayer } from './sqlite-storage';
|
|
69
|
+
|
|
70
|
+
// SqlTransaction.SqlTransaction is the Tag class exported from the SqlTransaction namespace.
|
|
71
|
+
type SqlTransactionTag = SqlTransaction.SqlTransaction;
|
|
67
72
|
|
|
68
73
|
export type ServiceContextRuntimeProps = Pick<
|
|
69
74
|
IdentityManagerProps,
|
|
@@ -74,493 +79,185 @@ export type ServiceContextRuntimeProps = Pick<
|
|
|
74
79
|
disableP2pReplication?: boolean;
|
|
75
80
|
enableVectorIndexing?: boolean;
|
|
76
81
|
};
|
|
82
|
+
|
|
77
83
|
/**
|
|
78
|
-
*
|
|
84
|
+
* Combined storage migration effect gathered from the concrete SQLite stores.
|
|
85
|
+
* Run by {@link ClientServicesHost} during open (storage migration stage).
|
|
79
86
|
*/
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
export class ServiceContext extends Resource {
|
|
85
|
-
private readonly _edgeIdentityUpdateMutex = new Mutex();
|
|
86
|
-
|
|
87
|
-
public readonly initialized = new Trigger();
|
|
88
|
-
public readonly metadataStore: SqliteMetadataStore;
|
|
89
|
-
public readonly blobStore: SqliteBlobStore;
|
|
90
|
-
public readonly feedStore: FeedStore<FeedMessage>;
|
|
91
|
-
public readonly keyring: SqliteKeyring;
|
|
92
|
-
public readonly spaceManager: SpaceManager;
|
|
93
|
-
public readonly identityManager: IdentityManager;
|
|
94
|
-
public readonly recoveryManager: EdgeIdentityRecoveryManager;
|
|
95
|
-
public readonly invitations: InvitationsHandler;
|
|
96
|
-
public readonly invitationsManager: InvitationsManager;
|
|
97
|
-
public readonly echoHost: EchoHost;
|
|
98
|
-
private readonly _meshReplicator?: MeshEchoReplicator = undefined;
|
|
99
|
-
private readonly _echoEdgeReplicator?: EdgeAutomergeReplicator = undefined;
|
|
100
|
-
private readonly _feedSyncer?: FeedSyncer = undefined;
|
|
101
|
-
private readonly _feedStorage: SqliteStorage;
|
|
87
|
+
export class StorageMigrationService extends EffectContext.Tag('@dxos/client-services/StorageMigration')<
|
|
88
|
+
StorageMigrationService,
|
|
89
|
+
Effect.Effect<void, SqlError.SqlError, SqlClient.SqlClient | SqlTransactionTag>
|
|
90
|
+
>() {}
|
|
102
91
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
92
|
+
export type ServiceContextLayerOptions = ServiceContextRuntimeProps & {
|
|
93
|
+
edgeFeatures?: Runtime.Client.EdgeFeatures;
|
|
94
|
+
edgeConnection?: EdgeConnection;
|
|
95
|
+
edgeHttpClient?: EdgeHttpClient;
|
|
96
|
+
};
|
|
106
97
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
98
|
+
/**
|
|
99
|
+
* Component tags the composed stack exposes so {@link ClientServicesHost} and the client RPC service
|
|
100
|
+
* layers can depend on each component directly.
|
|
101
|
+
*/
|
|
102
|
+
export type ServiceContextStackContext =
|
|
103
|
+
| EchoHostService
|
|
104
|
+
| IdentityManagerService
|
|
105
|
+
| IdentityProviderService
|
|
106
|
+
| SpaceManagerService
|
|
107
|
+
| InvitationsManagerService
|
|
108
|
+
| InvitationsHandlerService
|
|
109
|
+
| EdgeIdentityRecoveryManagerService
|
|
110
|
+
| KeyringApiService
|
|
111
|
+
| DataSpaceManagerService
|
|
112
|
+
| EdgeAgentManagerService
|
|
113
|
+
| CrossDeviceSpaceSynchronizerService
|
|
114
|
+
| SigningContextProviderService
|
|
115
|
+
| IMetadataStoreService
|
|
116
|
+
| BlobStoreApiService
|
|
117
|
+
| FeedStoreService
|
|
118
|
+
| StorageMigrationService;
|
|
127
119
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
120
|
+
/**
|
|
121
|
+
* Effect Layer composing the dormant client-stack components, constructed before identity is ready.
|
|
122
|
+
* {@link ClientServicesHost} resolves these tags and drives their lifecycle.
|
|
123
|
+
*/
|
|
124
|
+
export const ServiceContextLayer = (
|
|
125
|
+
options: ServiceContextLayerOptions,
|
|
126
|
+
): Layer.Layer<
|
|
127
|
+
ServiceContextStackContext,
|
|
128
|
+
never,
|
|
129
|
+
SwarmNetworkManagerService | SignalManagerService | SqlClient.SqlClient | SqlTransactionTag
|
|
130
|
+
> => {
|
|
131
|
+
const { edgeConnection, edgeHttpClient } = options;
|
|
132
|
+
|
|
133
|
+
// Core stack, flattened into a single pipe. Optional replicators expose their service via
|
|
134
|
+
// `provideMerge` and are read with `serviceOption` down the stack; their absence is modelled by
|
|
135
|
+
// not wiring the layer, not by a null value.
|
|
136
|
+
const core = CrossDeviceSpaceSynchronizerLayer.pipe(
|
|
137
|
+
Layer.provideMerge(EdgeAgentManagerLayer({ edgeFeatures: options.edgeFeatures })),
|
|
138
|
+
Layer.provideMerge(DataSpaceManagerLayer({ runtimeProps: options, edgeFeatures: options.edgeFeatures })),
|
|
139
|
+
Layer.provideMerge(SigningContextProviderLayer),
|
|
140
|
+
Layer.provideMerge(identityProviderLayer),
|
|
141
|
+
Layer.provideMerge(options.disableP2pReplication ? Layer.empty : MeshEchoReplicatorLayer()),
|
|
142
|
+
Layer.provideMerge(echoHostLayer({ useSubduction: options.edgeFeatures?.subductionReplicator })),
|
|
143
|
+
Layer.provideMerge(InvitationsManagerLayer()),
|
|
144
|
+
Layer.provideMerge(InvitationsHandlerLayer({ connectionProps: options.invitationConnectionDefaultProps })),
|
|
145
|
+
Layer.provideMerge(EdgeIdentityRecoveryManagerLayer()),
|
|
146
|
+
Layer.provideMerge(
|
|
147
|
+
IdentityManagerLayer({
|
|
148
|
+
devicePresenceOfflineTimeout: options.devicePresenceOfflineTimeout,
|
|
149
|
+
devicePresenceAnnounceInterval: options.devicePresenceAnnounceInterval,
|
|
150
|
+
edgeFeatures: options.edgeFeatures,
|
|
141
151
|
}),
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
this.identityManager = new IdentityManager({
|
|
153
|
-
metadataStore: this.metadataStore,
|
|
154
|
-
keyring: this.keyring,
|
|
155
|
-
feedStore: this.feedStore,
|
|
156
|
-
spaceManager: this.spaceManager,
|
|
157
|
-
devicePresenceOfflineTimeout: this._runtimeProps?.devicePresenceOfflineTimeout,
|
|
158
|
-
devicePresenceAnnounceInterval: this._runtimeProps?.devicePresenceAnnounceInterval,
|
|
159
|
-
edgeConnection: this._edgeConnection,
|
|
160
|
-
edgeFeatures: this._edgeFeatures,
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
this.recoveryManager = new EdgeIdentityRecoveryManager(
|
|
164
|
-
this.keyring,
|
|
165
|
-
this._edgeHttpClient,
|
|
166
|
-
() => this.identityManager.identity,
|
|
167
|
-
this._acceptIdentity.bind(this),
|
|
168
|
-
);
|
|
169
|
-
|
|
170
|
-
this.echoHost = new EchoHost({
|
|
171
|
-
peerIdProvider: () => this.identityManager.identity?.deviceKey?.toHex(),
|
|
172
|
-
getSpaceKeyByRootDocumentId: (documentId) => this.spaceManager.findSpaceByRootDocumentId(documentId)?.key,
|
|
173
|
-
runtime: this._runtime,
|
|
174
|
-
useSubduction: this._edgeFeatures?.subductionReplicator,
|
|
175
|
-
syncQueue: async (ctx, request) => {
|
|
176
|
-
return this._feedSyncer?.syncBlocking(ctx, {
|
|
177
|
-
spaceId: request.spaceId as SpaceId,
|
|
178
|
-
subspaceTag: request.subspaceTag,
|
|
179
|
-
shouldPush: request.shouldPush,
|
|
180
|
-
shouldPull: request.shouldPull,
|
|
181
|
-
});
|
|
182
|
-
},
|
|
183
|
-
getSyncState: async (ctx, request) => {
|
|
184
|
-
// Mirror `syncQueue` above: in non-edge / partially-initialised modes the
|
|
185
|
-
// feed syncer is absent. Return an empty state instead of throwing so
|
|
186
|
-
// callers (e.g. devtools sync panel) keep working.
|
|
187
|
-
if (!this._feedSyncer) {
|
|
188
|
-
return { namespaces: [] };
|
|
189
|
-
}
|
|
190
|
-
return this._feedSyncer.getSyncState(ctx, request);
|
|
191
|
-
},
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
this.invitations = new InvitationsHandler(
|
|
195
|
-
this.networkManager, //
|
|
196
|
-
this._edgeHttpClient,
|
|
197
|
-
_runtimeProps?.invitationConnectionDefaultProps,
|
|
198
|
-
);
|
|
199
|
-
this.invitationsManager = new InvitationsManager(
|
|
200
|
-
this.invitations,
|
|
201
|
-
(invitation) => this.getInvitationHandler(invitation),
|
|
202
|
-
this.metadataStore,
|
|
203
|
-
);
|
|
204
|
-
|
|
205
|
-
// TODO(burdon): _initialize called in multiple places.
|
|
206
|
-
// TODO(burdon): Call _initialize on success.
|
|
207
|
-
this._handlerFactories.set(
|
|
208
|
-
Invitation.Kind.DEVICE,
|
|
209
|
-
() =>
|
|
210
|
-
new DeviceInvitationProtocol(
|
|
211
|
-
this.keyring,
|
|
212
|
-
() => this.identityManager.identity ?? failUndefined(),
|
|
213
|
-
this._acceptIdentity.bind(this),
|
|
214
|
-
),
|
|
215
|
-
);
|
|
216
|
-
|
|
217
|
-
if (!this._runtimeProps?.disableP2pReplication) {
|
|
218
|
-
this._meshReplicator = new MeshEchoReplicator();
|
|
219
|
-
}
|
|
220
|
-
if (this._edgeConnection && this._edgeHttpClient) {
|
|
221
|
-
if (this._edgeFeatures?.subductionReplicator) {
|
|
222
|
-
this._echoEdgeReplicator = new EchoEdgeSubductionReplicator({
|
|
223
|
-
edgeConnection: this._edgeConnection,
|
|
224
|
-
edgeHttpClient: this._edgeHttpClient,
|
|
225
|
-
});
|
|
226
|
-
} else if (this._edgeFeatures?.echoReplicator) {
|
|
227
|
-
this._echoEdgeReplicator = new EchoEdgeReplicator({
|
|
228
|
-
edgeConnection: this._edgeConnection,
|
|
229
|
-
edgeHttpClient: this._edgeHttpClient,
|
|
230
|
-
});
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
if (this.echoHost.feedStore && this._edgeConnection) {
|
|
235
|
-
this._feedSyncer = new FeedSyncer({
|
|
236
|
-
runtime: this._runtime,
|
|
237
|
-
feedStore: this.echoHost.feedStore,
|
|
238
|
-
edgeClient: this._edgeConnection,
|
|
239
|
-
peerId: this.identityManager.identity?.deviceKey?.toHex() ?? '',
|
|
240
|
-
getSpaceIds: () => this.echoHost!.spaceIds,
|
|
241
|
-
syncNamespaces: [FeedProtocol.WellKnownNamespaces.data, FeedProtocol.WellKnownNamespaces.trace],
|
|
242
|
-
});
|
|
243
|
-
}
|
|
152
|
+
),
|
|
153
|
+
Layer.provideMerge(SpaceManagerLayer({ disableP2pReplication: options.disableP2pReplication })),
|
|
154
|
+
Layer.provideMerge(storageLayer),
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
// Non-edge: just the core.
|
|
158
|
+
if (!edgeConnection || !edgeHttpClient) {
|
|
159
|
+
return core;
|
|
244
160
|
}
|
|
245
161
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
await this._edgeConnection?.open(ctx);
|
|
270
|
-
log('edge connection opened');
|
|
271
|
-
|
|
272
|
-
log('opening signal manager...');
|
|
273
|
-
await this.signalManager.open(ctx);
|
|
274
|
-
log('signal manager opened');
|
|
275
|
-
|
|
276
|
-
log('opening network manager...');
|
|
277
|
-
await this.networkManager.open();
|
|
278
|
-
log('network manager opened');
|
|
279
|
-
|
|
280
|
-
log('opening echo host...');
|
|
281
|
-
await this.echoHost.open(ctx);
|
|
282
|
-
log('echo host opened');
|
|
283
|
-
|
|
284
|
-
if (this._meshReplicator) {
|
|
285
|
-
log('adding mesh replicator...');
|
|
286
|
-
await this.echoHost.addReplicator(ctx, this._meshReplicator);
|
|
287
|
-
log('mesh replicator added');
|
|
288
|
-
}
|
|
289
|
-
if (this._echoEdgeReplicator) {
|
|
290
|
-
log('adding edge replicator...');
|
|
291
|
-
await this.echoHost.addReplicator(ctx, this._echoEdgeReplicator);
|
|
292
|
-
log('edge replicator added');
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
log('loading metadata store...');
|
|
296
|
-
await this.metadataStore.load();
|
|
297
|
-
log('metadata store loaded');
|
|
298
|
-
|
|
299
|
-
log('opening space manager...');
|
|
300
|
-
await this.spaceManager.open();
|
|
301
|
-
log('space manager opened');
|
|
302
|
-
|
|
303
|
-
if (this.identityManager.identity) {
|
|
304
|
-
log('joining network...');
|
|
305
|
-
await this.identityManager.identity.joinNetwork(ctx);
|
|
306
|
-
log('network joined');
|
|
162
|
+
// Edge: the feed syncer sits above the core for its `EchoHostService` requirement; the edge
|
|
163
|
+
// replicator sits below — it needs only the edge inputs, resolved via `serviceOption` inside the
|
|
164
|
+
// core. Edge inputs are provided internally so they never surface as stack requirements.
|
|
165
|
+
return FeedSyncerLayer({
|
|
166
|
+
peerId: '',
|
|
167
|
+
syncNamespaces: [FeedProtocol.WellKnownNamespaces.data, FeedProtocol.WellKnownNamespaces.trace],
|
|
168
|
+
}).pipe(
|
|
169
|
+
Layer.provideMerge(core),
|
|
170
|
+
Layer.provideMerge(
|
|
171
|
+
options.edgeFeatures?.subductionReplicator
|
|
172
|
+
? EchoEdgeSubductionReplicatorLayer()
|
|
173
|
+
: options.edgeFeatures?.echoReplicator
|
|
174
|
+
? EchoEdgeReplicatorLayer()
|
|
175
|
+
: Layer.empty,
|
|
176
|
+
),
|
|
177
|
+
Layer.provideMerge(
|
|
178
|
+
Layer.mergeAll(
|
|
179
|
+
Layer.succeed(EdgeConnectionService, edgeConnection),
|
|
180
|
+
Layer.succeed(EdgeHttpClientService, edgeHttpClient),
|
|
181
|
+
),
|
|
182
|
+
),
|
|
183
|
+
);
|
|
184
|
+
};
|
|
307
185
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
log('loading persistent invitations...');
|
|
320
|
-
const loadedInvitations = await this.invitationsManager.loadPersistentInvitations(ctx);
|
|
321
|
-
log('loaded persistent invitations', { count: loadedInvitations.invitations?.length });
|
|
322
|
-
|
|
323
|
-
log('opened');
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
protected override async _close(ctx: Context): Promise<void> {
|
|
327
|
-
log('closing...');
|
|
328
|
-
|
|
329
|
-
await this._feedSyncer?.close();
|
|
330
|
-
|
|
331
|
-
if (this._deviceSpaceSync && this.identityManager.identity) {
|
|
332
|
-
await this.identityManager.identity.space.spaceState.removeCredentialProcessor(this._deviceSpaceSync);
|
|
333
|
-
}
|
|
334
|
-
await this.dataSpaceManager?.close(ctx);
|
|
335
|
-
await this.edgeAgentManager?.close();
|
|
336
|
-
await this.identityManager.close(ctx);
|
|
337
|
-
await this.spaceManager.close();
|
|
338
|
-
await this.echoHost.close(ctx);
|
|
339
|
-
|
|
340
|
-
await this.networkManager.close(ctx);
|
|
341
|
-
await this.signalManager.close();
|
|
342
|
-
await this._edgeConnection?.close();
|
|
343
|
-
await this.feedStore.close();
|
|
344
|
-
await this.metadataStore.close();
|
|
345
|
-
|
|
346
|
-
log('closed');
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
async createIdentity(params: CreateIdentityOptions = {}, ctx?: Context) {
|
|
350
|
-
ctx ??= this._ctx;
|
|
351
|
-
const identity = await this.identityManager.createIdentity(params, ctx);
|
|
352
|
-
await this._setNetworkIdentity({ identity });
|
|
353
|
-
await identity.joinNetwork(ctx);
|
|
354
|
-
await this._initialize(ctx);
|
|
355
|
-
return identity;
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
getInvitationHandler(invitation: Partial<Invitation> & Pick<Invitation, 'kind'>): InvitationProtocol {
|
|
359
|
-
if (this.identityManager.identity == null && invitation.kind === Invitation.Kind.SPACE) {
|
|
360
|
-
throw new Error('Identity must be created before joining a space.');
|
|
361
|
-
}
|
|
362
|
-
const factory = this._handlerFactories.get(invitation.kind);
|
|
363
|
-
invariant(factory, `Unknown invitation kind: ${invitation.kind}`);
|
|
364
|
-
return factory(invitation);
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
async broadcastProfileUpdate(profile: ProfileDocument | undefined): Promise<void> {
|
|
368
|
-
if (!profile || !this.dataSpaceManager) {
|
|
369
|
-
return;
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
for (const space of this.dataSpaceManager.spaces.values()) {
|
|
373
|
-
await space.updateOwnProfile(profile);
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
private async _acceptIdentity(params: JoinIdentityProps) {
|
|
378
|
-
const { identity, identityRecord } = await this.identityManager.prepareIdentity(params, this._ctx);
|
|
379
|
-
await this._setNetworkIdentity({ deviceCredential: params.authorizedDeviceCredential!, identity });
|
|
380
|
-
await identity.joinNetwork(this._ctx);
|
|
381
|
-
await this.identityManager.acceptIdentity(identity, identityRecord, params.deviceProfile);
|
|
382
|
-
await this._initialize(this._ctx);
|
|
383
|
-
return identity;
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
private async _checkStorageVersion(): Promise<void> {
|
|
387
|
-
await this.metadataStore.load();
|
|
388
|
-
if (this.metadataStore.version !== STORAGE_VERSION) {
|
|
389
|
-
throw new InvalidStorageVersionError(STORAGE_VERSION, this.metadataStore.version);
|
|
390
|
-
// TODO(mykola): Migrate storage to a new version if incompatibility is detected.
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
// Called when identity is created.
|
|
395
|
-
@Trace.span()
|
|
396
|
-
private async _initialize(ctx: Context): Promise<void> {
|
|
397
|
-
log('_initialize: start');
|
|
398
|
-
const identity = this.identityManager.identity ?? failUndefined();
|
|
399
|
-
const signingContext: SigningContext = {
|
|
400
|
-
credentialSigner: identity.getIdentityCredentialSigner(),
|
|
401
|
-
identityKey: identity.identityKey,
|
|
402
|
-
deviceKey: identity.deviceKey,
|
|
403
|
-
getProfile: () => identity.profileDocument,
|
|
404
|
-
recordCredential: async (credential) => {
|
|
405
|
-
await identity.controlPipeline.writer.write({ credential: { credential } });
|
|
406
|
-
},
|
|
407
|
-
};
|
|
408
|
-
|
|
409
|
-
log('_initialize: creating DataSpaceManager');
|
|
410
|
-
this.dataSpaceManager = new DataSpaceManager({
|
|
411
|
-
spaceManager: this.spaceManager,
|
|
412
|
-
metadataStore: this.metadataStore,
|
|
413
|
-
keyring: this.keyring,
|
|
414
|
-
signingContext,
|
|
415
|
-
feedStore: this.feedStore,
|
|
416
|
-
echoHost: this.echoHost,
|
|
417
|
-
invitationsManager: this.invitationsManager,
|
|
418
|
-
edgeConnection: this._edgeConnection,
|
|
419
|
-
edgeHttpClient: this._edgeHttpClient,
|
|
420
|
-
echoEdgeReplicator: this._echoEdgeReplicator,
|
|
421
|
-
meshReplicator: this._meshReplicator,
|
|
422
|
-
runtimeProps: this._runtimeProps as DataSpaceManagerRuntimeProps,
|
|
423
|
-
edgeFeatures: this._edgeFeatures,
|
|
424
|
-
});
|
|
425
|
-
log('_initialize: opening DataSpaceManager...');
|
|
426
|
-
await this.dataSpaceManager.open(ctx);
|
|
427
|
-
log('_initialize: DataSpaceManager opened');
|
|
186
|
+
/**
|
|
187
|
+
* Provides the {@link IdentityProviderService} from the resolved {@link IdentityManager}.
|
|
188
|
+
*/
|
|
189
|
+
const identityProviderLayer = Layer.effect(
|
|
190
|
+
IdentityProviderService,
|
|
191
|
+
Effect.gen(function* () {
|
|
192
|
+
const identityManager = yield* IdentityManagerService;
|
|
193
|
+
return identityProviderFromManager(identityManager);
|
|
194
|
+
}),
|
|
195
|
+
);
|
|
428
196
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
197
|
+
/**
|
|
198
|
+
* Combined storage migration effect. Storage migrations are idempotent `CREATE TABLE` effects that
|
|
199
|
+
* do not depend on store instance state, so they are extracted from throwaway instances to keep the
|
|
200
|
+
* store layers individual. Run by {@link ClientServicesHost} during open.
|
|
201
|
+
*/
|
|
202
|
+
const storageMigrationLayer = Layer.effect(
|
|
203
|
+
StorageMigrationService,
|
|
204
|
+
Effect.gen(function* () {
|
|
205
|
+
const runtime = yield* RuntimeProvider.currentRuntime<SqlClient.SqlClient | SqlTransactionTag>();
|
|
206
|
+
return Effect.all(
|
|
207
|
+
[
|
|
208
|
+
new SqliteMetadataStore({ runtime }).migrate,
|
|
209
|
+
new SqliteBlobStore({ runtime }).migrate,
|
|
210
|
+
new SqliteKeyring({ runtime }).migrate,
|
|
211
|
+
new SqliteStorage({ runtime }).migrate,
|
|
212
|
+
],
|
|
213
|
+
{ discard: true },
|
|
434
214
|
);
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
log('_initialize: EdgeAgentManager opened');
|
|
438
|
-
|
|
439
|
-
this._handlerFactories.set(Invitation.Kind.SPACE, (invitation) => {
|
|
440
|
-
invariant(this.dataSpaceManager, 'dataSpaceManager not initialized yet');
|
|
441
|
-
return new SpaceInvitationProtocol(this.dataSpaceManager, signingContext, this.keyring, invitation.spaceKey);
|
|
442
|
-
});
|
|
443
|
-
this.initialized.wake();
|
|
444
|
-
log('_initialize: initialized.wake() called');
|
|
215
|
+
}),
|
|
216
|
+
);
|
|
445
217
|
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
try {
|
|
462
|
-
log('tombstoning space recorded in halo', { details: assertion });
|
|
463
|
-
await this.dataSpaceManager.handleRemoteSpaceDeleted(this._ctx, assertion.spaceKey);
|
|
464
|
-
} catch (err) {
|
|
465
|
-
log.catch(err);
|
|
466
|
-
}
|
|
467
|
-
return;
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
if (assertion['@type'] !== 'dxos.halo.credentials.SpaceMember') {
|
|
471
|
-
return;
|
|
472
|
-
}
|
|
473
|
-
if (assertion.spaceKey.equals(identity.space.key)) {
|
|
474
|
-
// ignore halo space
|
|
475
|
-
return;
|
|
476
|
-
}
|
|
477
|
-
if (!this.dataSpaceManager) {
|
|
478
|
-
log('dataSpaceManager not initialized yet, ignoring space admission', { details: assertion });
|
|
479
|
-
return;
|
|
480
|
-
}
|
|
481
|
-
// Do not re-accept a space that has been tombstoned (handles out-of-order credential replay).
|
|
482
|
-
if (this.dataSpaceManager.isSpaceDeleted(assertion.spaceKey)) {
|
|
483
|
-
log('space is deleted, ignoring space admission', { details: assertion });
|
|
484
|
-
return;
|
|
485
|
-
}
|
|
486
|
-
if (this.dataSpaceManager.spaces.has(assertion.spaceKey)) {
|
|
487
|
-
log('space already exists, ignoring space admission', { details: assertion });
|
|
488
|
-
return;
|
|
489
|
-
}
|
|
218
|
+
/**
|
|
219
|
+
* Storage / feed layers composed from the individual store layers plus the combined migration.
|
|
220
|
+
*/
|
|
221
|
+
const storageLayer = Layer.empty.pipe(
|
|
222
|
+
Layer.provideMerge(FeedStoreLayer()),
|
|
223
|
+
Layer.provideMerge(FeedFactoryLayer({ hypercore: { valueEncoding, stats: true } })),
|
|
224
|
+
Layer.provideMerge(FeedStorageDirectoryLayer()),
|
|
225
|
+
Layer.provideMerge(SqliteMetadataStoreLayer()),
|
|
226
|
+
Layer.provideMerge(SqliteBlobStoreLayer()),
|
|
227
|
+
Layer.provideMerge(SqliteKeyringLayer()),
|
|
228
|
+
Layer.provideMerge(SqliteStorageLayer()),
|
|
229
|
+
Layer.provideMerge(storageMigrationLayer),
|
|
230
|
+
);
|
|
490
231
|
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
232
|
+
/**
|
|
233
|
+
* Constructs the {@link EchoHost}, resolving the identity/space callbacks that point down the stack.
|
|
234
|
+
* The feed sync handlers (which point up) are wired later via `EchoHost.setFeedSyncHandlers`.
|
|
235
|
+
*
|
|
236
|
+
* The host is self-contained (runs its own migrations, owns its feed/automerge stores), so its
|
|
237
|
+
* open/close is owned by the layer scope: it opens when the stack is built and closes when the
|
|
238
|
+
* runtime is disposed. Identity-, network-, and storage-bound lifecycle stays in `ClientServicesHost`.
|
|
239
|
+
*/
|
|
240
|
+
const echoHostLayer = (options: { useSubduction?: boolean }) =>
|
|
241
|
+
Layer.scopedDiscard(
|
|
242
|
+
Effect.gen(function* () {
|
|
243
|
+
const echoHost = yield* EchoHostService;
|
|
244
|
+
yield* Effect.acquireRelease(
|
|
245
|
+
Effect.promise(() => echoHost.open()),
|
|
246
|
+
() => Effect.promise(() => echoHost.close()),
|
|
247
|
+
);
|
|
248
|
+
}),
|
|
249
|
+
).pipe(
|
|
250
|
+
Layer.provideMerge(
|
|
251
|
+
Layer.unwrapEffect(
|
|
252
|
+
Effect.gen(function* () {
|
|
253
|
+
const identityManager = yield* IdentityManagerService;
|
|
254
|
+
const spaceManager = yield* SpaceManagerService;
|
|
255
|
+
return EchoHostLayer({
|
|
256
|
+
peerIdProvider: () => identityManager.identity?.deviceKey?.toHex(),
|
|
257
|
+
getSpaceKeyByRootDocumentId: (documentId) => spaceManager.findSpaceByRootDocumentId(documentId)?.key,
|
|
258
|
+
useSubduction: options.useSubduction,
|
|
497
259
|
});
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
};
|
|
503
|
-
|
|
504
|
-
await identity.space.spaceState.addCredentialProcessor(this._deviceSpaceSync);
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
private async _setNetworkIdentity(params?: { deviceCredential?: Credential; identity?: Identity }): Promise<void> {
|
|
508
|
-
log('_setNetworkIdentity: acquiring mutex...');
|
|
509
|
-
using _ = await this._edgeIdentityUpdateMutex.acquire();
|
|
510
|
-
log('_setNetworkIdentity: mutex acquired');
|
|
511
|
-
|
|
512
|
-
let edgeIdentity: EdgeIdentity;
|
|
513
|
-
const identity = params?.identity;
|
|
514
|
-
if (identity) {
|
|
515
|
-
log('_setNetworkIdentity: has identity', {
|
|
516
|
-
identity: identity.identityKey.toHex(),
|
|
517
|
-
hasDeviceCredential: !!params?.deviceCredential,
|
|
518
|
-
});
|
|
519
|
-
|
|
520
|
-
if (params?.deviceCredential) {
|
|
521
|
-
log('_setNetworkIdentity: creating chain edge identity with device credential...');
|
|
522
|
-
edgeIdentity = await createChainEdgeIdentity(
|
|
523
|
-
identity.signer,
|
|
524
|
-
identity.identityKey,
|
|
525
|
-
identity.deviceKey,
|
|
526
|
-
{ credential: params.deviceCredential },
|
|
527
|
-
[], // TODO(dmaretskyi): Service access credentials.
|
|
528
|
-
);
|
|
529
|
-
log('_setNetworkIdentity: chain edge identity created');
|
|
530
|
-
} else {
|
|
531
|
-
log('_setNetworkIdentity: waiting for identity.ready()...');
|
|
532
|
-
// TODO: throw here or from identity if device chain can't be loaded, to avoid indefinite hangup
|
|
533
|
-
await warnAfterTimeout(10_000, 'Waiting for identity to be ready for edge connection', async () => {
|
|
534
|
-
await identity.ready();
|
|
535
|
-
});
|
|
536
|
-
log('_setNetworkIdentity: identity.ready() resolved', {
|
|
537
|
-
hasDeviceCredentialChain: !!identity.deviceCredentialChain,
|
|
538
|
-
});
|
|
539
|
-
|
|
540
|
-
invariant(identity.deviceCredentialChain);
|
|
541
|
-
|
|
542
|
-
log('_setNetworkIdentity: creating chain edge identity...');
|
|
543
|
-
edgeIdentity = await createChainEdgeIdentity(
|
|
544
|
-
identity.signer,
|
|
545
|
-
identity.identityKey,
|
|
546
|
-
identity.deviceKey,
|
|
547
|
-
identity.deviceCredentialChain,
|
|
548
|
-
[], // TODO(dmaretskyi): Service access credentials.
|
|
549
|
-
);
|
|
550
|
-
log('_setNetworkIdentity: chain edge identity created');
|
|
551
|
-
}
|
|
552
|
-
} else {
|
|
553
|
-
log('_setNetworkIdentity: no identity, creating ephemeral edge identity...');
|
|
554
|
-
edgeIdentity = await createEphemeralEdgeIdentity();
|
|
555
|
-
log('_setNetworkIdentity: ephemeral edge identity created');
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
this._edgeConnection?.setIdentity(edgeIdentity);
|
|
559
|
-
this._edgeHttpClient?.setIdentity(edgeIdentity);
|
|
560
|
-
this.networkManager.setPeerInfo({
|
|
561
|
-
identityDid: edgeIdentity.identityDid,
|
|
562
|
-
peerKey: edgeIdentity.peerKey,
|
|
563
|
-
});
|
|
564
|
-
log('_setNetworkIdentity: done');
|
|
565
|
-
}
|
|
566
|
-
}
|
|
260
|
+
}),
|
|
261
|
+
),
|
|
262
|
+
),
|
|
263
|
+
);
|