@dxos/plugin-client 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/ClientPlugin.mjs +65 -0
- package/dist/lib/ClientPlugin.mjs.map +1 -0
- package/dist/lib/ClientPlugin.node.mjs +904 -0
- package/dist/lib/ClientPlugin.node.mjs.map +1 -0
- package/dist/lib/ClientPlugin.workerd.mjs +10 -0
- package/dist/lib/ClientPlugin.workerd.mjs.map +1 -0
- package/dist/lib/capabilities/node.mjs +13 -0
- package/dist/lib/capabilities/node.mjs.map +1 -0
- package/dist/lib/capabilities.mjs +23 -0
- package/dist/lib/capabilities.mjs.map +1 -0
- package/dist/lib/chunk-AccountContainer.mjs +190 -0
- package/dist/lib/chunk-AccountContainer.mjs.map +1 -0
- package/dist/lib/chunk-DevicesContainer.mjs +275 -0
- package/dist/lib/chunk-DevicesContainer.mjs.map +1 -0
- package/dist/lib/chunk-InvitationsContainer.mjs +149 -0
- package/dist/lib/chunk-InvitationsContainer.mjs.map +1 -0
- package/dist/lib/chunk-JoinDialog.mjs +35 -0
- package/dist/lib/chunk-JoinDialog.mjs.map +1 -0
- package/dist/lib/chunk-ProfileContainer.mjs +145 -0
- package/dist/lib/chunk-ProfileContainer.mjs.map +1 -0
- package/dist/lib/chunk-RecoveryCodeDialog.mjs +72 -0
- package/dist/lib/chunk-RecoveryCodeDialog.mjs.map +1 -0
- package/dist/lib/chunk-RecoveryCredentialsContainer.mjs +65 -0
- package/dist/lib/chunk-RecoveryCredentialsContainer.mjs.map +1 -0
- package/dist/lib/chunk-ResetDialog.mjs +47 -0
- package/dist/lib/chunk-ResetDialog.mjs.map +1 -0
- package/dist/lib/chunk-UsageContainer.mjs +217 -0
- package/dist/lib/chunk-UsageContainer.mjs.map +1 -0
- package/dist/lib/{neutral/account-cache-YVQKLNV2.mjs → chunk-account-cache.mjs} +10 -12
- package/dist/lib/chunk-account-cache.mjs.map +1 -0
- package/dist/lib/chunk-app-graph-builder.mjs +111 -0
- package/dist/lib/chunk-app-graph-builder.mjs.map +1 -0
- package/dist/lib/chunk-client.mjs +90 -0
- package/dist/lib/chunk-client.mjs.map +1 -0
- package/dist/lib/{neutral/chunk-GSKMAS3S.mjs → chunk-constants.mjs} +5 -8
- package/dist/lib/chunk-constants.mjs.map +1 -0
- package/dist/lib/chunk-create-agent.mjs +23 -0
- package/dist/lib/chunk-create-agent.mjs.map +1 -0
- package/dist/lib/chunk-create-identity.mjs +28 -0
- package/dist/lib/chunk-create-identity.mjs.map +1 -0
- package/dist/lib/chunk-create-passkey.mjs +85 -0
- package/dist/lib/chunk-create-passkey.mjs.map +1 -0
- package/dist/lib/chunk-create-recovery-code.mjs +31 -0
- package/dist/lib/chunk-create-recovery-code.mjs.map +1 -0
- package/dist/lib/chunk-hooks.mjs +29 -0
- package/dist/lib/chunk-hooks.mjs.map +1 -0
- package/dist/lib/chunk-hub-http-client.mjs +14 -0
- package/dist/lib/chunk-hub-http-client.mjs.map +1 -0
- package/dist/lib/chunk-join-identity.mjs +20 -0
- package/dist/lib/chunk-join-identity.mjs.map +1 -0
- package/dist/lib/chunk-layer-specs.mjs +107 -0
- package/dist/lib/chunk-layer-specs.mjs.map +1 -0
- package/dist/lib/{neutral/chunk-6G4KZLBG.mjs → chunk-meta.mjs} +13 -20
- package/dist/lib/chunk-meta.mjs.map +1 -0
- package/dist/lib/chunk-migrations.mjs +29 -0
- package/dist/lib/chunk-migrations.mjs.map +1 -0
- package/dist/lib/chunk-navigation-handler.mjs +71 -0
- package/dist/lib/chunk-navigation-handler.mjs.map +1 -0
- package/dist/lib/chunk-navigation-target-loader.mjs +46 -0
- package/dist/lib/chunk-navigation-target-loader.mjs.map +1 -0
- package/dist/lib/chunk-open-usage.mjs +14 -0
- package/dist/lib/chunk-open-usage.mjs.map +1 -0
- package/dist/lib/chunk-operation-handler.mjs +11 -0
- package/dist/lib/chunk-operation-handler.mjs.map +1 -0
- package/dist/lib/chunk-operations.mjs +212 -0
- package/dist/lib/chunk-operations.mjs.map +1 -0
- package/dist/lib/chunk-progress.mjs +10 -0
- package/dist/lib/chunk-progress.mjs.map +1 -0
- package/dist/lib/chunk-react-context.mjs +30 -0
- package/dist/lib/chunk-react-context.mjs.map +1 -0
- package/dist/lib/chunk-react-surface.mjs +70 -0
- package/dist/lib/chunk-react-surface.mjs.map +1 -0
- package/dist/lib/chunk-recover-identity.mjs +17 -0
- package/dist/lib/chunk-recover-identity.mjs.map +1 -0
- package/dist/lib/chunk-redeem-passkey.mjs +72 -0
- package/dist/lib/chunk-redeem-passkey.mjs.map +1 -0
- package/dist/lib/chunk-redeem-token.mjs +24 -0
- package/dist/lib/chunk-redeem-token.mjs.map +1 -0
- package/dist/lib/chunk-remote-trace-monitor.mjs +37 -0
- package/dist/lib/chunk-remote-trace-monitor.mjs.map +1 -0
- package/dist/lib/chunk-reset-storage.mjs +17 -0
- package/dist/lib/chunk-reset-storage.mjs.map +1 -0
- package/dist/lib/chunk-resolve-navigation-targets.mjs +32 -0
- package/dist/lib/chunk-resolve-navigation-targets.mjs.map +1 -0
- package/dist/lib/chunk-schema-defs.mjs +53 -0
- package/dist/lib/chunk-schema-defs.mjs.map +1 -0
- package/dist/lib/chunk-share-identity.mjs +16 -0
- package/dist/lib/chunk-share-identity.mjs.map +1 -0
- package/dist/lib/chunk-space-replication-progress.mjs +94 -0
- package/dist/lib/chunk-space-replication-progress.mjs.map +1 -0
- package/dist/lib/chunk-trace-progress.mjs +69 -0
- package/dist/lib/chunk-trace-progress.mjs.map +1 -0
- package/dist/lib/chunk-update-profile.mjs +15 -0
- package/dist/lib/chunk-update-profile.mjs.map +1 -0
- package/dist/lib/components.mjs +0 -0
- package/dist/lib/containers.mjs +15 -0
- package/dist/lib/containers.mjs.map +1 -0
- package/dist/lib/index.mjs +27 -0
- package/dist/lib/index.mjs.map +1 -0
- package/dist/lib/meta.mjs +2 -0
- package/dist/lib/operations.mjs +2 -0
- package/dist/lib/plugin.mjs +9 -0
- package/dist/lib/plugin.mjs.map +1 -0
- package/dist/lib/testing.mjs +21 -0
- package/dist/lib/testing.mjs.map +1 -0
- package/dist/lib/translations.mjs +111 -0
- package/dist/lib/translations.mjs.map +1 -0
- package/dist/lib/types.mjs +139 -0
- package/dist/lib/types.mjs.map +1 -0
- package/dist/types/src/ClientPlugin.d.ts.map +1 -1
- package/dist/types/src/capabilities/account-cache.d.ts +1 -1
- package/dist/types/src/capabilities/app-graph-builder.d.ts +1 -1
- package/dist/types/src/capabilities/client.d.ts +1 -1
- package/dist/types/src/capabilities/client.d.ts.map +1 -1
- package/dist/types/src/capabilities/hub-http-client.d.ts +1 -1
- package/dist/types/src/capabilities/index.d.ts +6 -1
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/layer-specs.d.ts +1 -1
- package/dist/types/src/capabilities/migrations.d.ts +1 -1
- package/dist/types/src/capabilities/navigation-handler/navigation-handler.d.ts +3 -1
- package/dist/types/src/capabilities/navigation-handler/navigation-handler.d.ts.map +1 -1
- package/dist/types/src/capabilities/navigation-target-loader.d.ts +11 -0
- package/dist/types/src/capabilities/navigation-target-loader.d.ts.map +1 -0
- package/dist/types/src/capabilities/node.d.ts +2 -1
- package/dist/types/src/capabilities/node.d.ts.map +1 -1
- package/dist/types/src/capabilities/operation-handler.d.ts +1 -1
- package/dist/types/src/capabilities/react-context.d.ts +1 -1
- package/dist/types/src/capabilities/react-context.d.ts.map +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
- package/dist/types/src/capabilities/remote-trace-monitor.d.ts +15 -0
- package/dist/types/src/capabilities/remote-trace-monitor.d.ts.map +1 -0
- package/dist/types/src/capabilities/schema-defs.d.ts +1 -1
- package/dist/types/src/capabilities/space-replication-progress.d.ts +11 -0
- package/dist/types/src/capabilities/space-replication-progress.d.ts.map +1 -0
- package/dist/types/src/capabilities/trace-progress.d.ts +17 -0
- package/dist/types/src/capabilities/trace-progress.d.ts.map +1 -0
- package/dist/types/src/commands/account/login/login.d.ts +2 -1
- package/dist/types/src/commands/account/login/login.d.ts.map +1 -1
- package/dist/types/src/commands/account/logout/logout.d.ts +1 -1
- package/dist/types/src/commands/account/logout/logout.d.ts.map +1 -1
- package/dist/types/src/commands/halo/index.d.ts.map +1 -1
- package/dist/types/src/commands/halo/share/share.d.ts.map +1 -1
- package/dist/types/src/commands/profile/create.d.ts.map +1 -1
- package/dist/types/src/containers/AccountContainer/AccountContainer.d.ts +4 -1
- package/dist/types/src/containers/AccountContainer/AccountContainer.d.ts.map +1 -1
- package/dist/types/src/containers/AccountContainer/AccountContainer.stories.d.ts +4 -1
- package/dist/types/src/containers/AccountContainer/AccountContainer.stories.d.ts.map +1 -1
- package/dist/types/src/containers/DevicesContainer/DevicesContainer.d.ts +4 -1
- package/dist/types/src/containers/DevicesContainer/DevicesContainer.d.ts.map +1 -1
- package/dist/types/src/containers/DevicesContainer/DevicesContainer.stories.d.ts +4 -1
- package/dist/types/src/containers/DevicesContainer/DevicesContainer.stories.d.ts.map +1 -1
- package/dist/types/src/containers/InvitationsContainer/InvitationsContainer.d.ts +4 -1
- package/dist/types/src/containers/InvitationsContainer/InvitationsContainer.d.ts.map +1 -1
- package/dist/types/src/containers/InvitationsContainer/InvitationsContainer.stories.d.ts +4 -1
- package/dist/types/src/containers/InvitationsContainer/InvitationsContainer.stories.d.ts.map +1 -1
- package/dist/types/src/containers/JoinDialog/JoinDialog.d.ts +4 -1
- package/dist/types/src/containers/JoinDialog/JoinDialog.d.ts.map +1 -1
- package/dist/types/src/containers/JoinDialog/JoinDialog.stories.d.ts +4 -1
- package/dist/types/src/containers/JoinDialog/JoinDialog.stories.d.ts.map +1 -1
- package/dist/types/src/containers/ProfileContainer/ProfileContainer.d.ts +4 -1
- package/dist/types/src/containers/ProfileContainer/ProfileContainer.d.ts.map +1 -1
- package/dist/types/src/containers/ProfileContainer/ProfileContainer.stories.d.ts +4 -1
- package/dist/types/src/containers/ProfileContainer/ProfileContainer.stories.d.ts.map +1 -1
- package/dist/types/src/containers/RecoveryCodeDialog/RecoveryCodeDialog.d.ts +4 -1
- package/dist/types/src/containers/RecoveryCodeDialog/RecoveryCodeDialog.d.ts.map +1 -1
- package/dist/types/src/containers/RecoveryCredentialsContainer/RecoveryCredentialsContainer.d.ts +4 -1
- package/dist/types/src/containers/RecoveryCredentialsContainer/RecoveryCredentialsContainer.d.ts.map +1 -1
- package/dist/types/src/containers/RecoveryCredentialsContainer/RecoveryCredentialsContainer.stories.d.ts +4 -1
- package/dist/types/src/containers/RecoveryCredentialsContainer/RecoveryCredentialsContainer.stories.d.ts.map +1 -1
- package/dist/types/src/containers/ResetDialog/ResetDialog.d.ts +4 -1
- package/dist/types/src/containers/ResetDialog/ResetDialog.d.ts.map +1 -1
- package/dist/types/src/containers/ResetDialog/ResetDialog.stories.d.ts +4 -1
- package/dist/types/src/containers/ResetDialog/ResetDialog.stories.d.ts.map +1 -1
- package/dist/types/src/containers/UsageContainer/UsageContainer.d.ts +4 -5
- package/dist/types/src/containers/UsageContainer/UsageContainer.d.ts.map +1 -1
- package/dist/types/src/containers/UsageContainer/UsageView.d.ts +4 -7
- package/dist/types/src/containers/UsageContainer/UsageView.d.ts.map +1 -1
- package/dist/types/src/containers/UsageContainer/UsageView.stories.d.ts +4 -2
- package/dist/types/src/containers/UsageContainer/UsageView.stories.d.ts.map +1 -1
- package/dist/types/src/halo-services-layer.d.ts +19 -0
- package/dist/types/src/halo-services-layer.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +3 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/operations/definitions.d.ts +9 -1
- package/dist/types/src/operations/definitions.d.ts.map +1 -1
- package/dist/types/src/operations/errors.d.ts +109 -0
- package/dist/types/src/operations/errors.d.ts.map +1 -0
- package/dist/types/src/operations/errors.test.d.ts +2 -0
- package/dist/types/src/operations/errors.test.d.ts.map +1 -0
- package/dist/types/src/operations/index.d.ts +1 -0
- package/dist/types/src/operations/index.d.ts.map +1 -1
- package/dist/types/src/operations/redeem-passkey.d.ts.map +1 -1
- package/dist/types/src/operations/resolve-navigation-targets.d.ts +5 -0
- package/dist/types/src/operations/resolve-navigation-targets.d.ts.map +1 -0
- package/dist/types/src/operations/update-profile.d.ts +5 -0
- package/dist/types/src/operations/update-profile.d.ts.map +1 -0
- package/dist/types/src/progress/index.d.ts +2 -0
- package/dist/types/src/progress/index.d.ts.map +1 -0
- package/dist/types/src/progress/progress-keys.d.ts +6 -0
- package/dist/types/src/progress/progress-keys.d.ts.map +1 -0
- package/dist/types/src/testing/initializeIdentity.d.ts +5 -1
- package/dist/types/src/testing/initializeIdentity.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/capabilities.d.ts +10 -1
- package/dist/types/src/types/capabilities.d.ts.map +1 -1
- package/dist/types/src/types/schema.d.ts +6 -0
- package/dist/types/src/types/schema.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +60 -55
- package/src/ClientPlugin.ts +25 -2
- package/src/capabilities/app-graph-builder.ts +1 -1
- package/src/capabilities/client.ts +26 -0
- package/src/capabilities/index.ts +10 -0
- package/src/capabilities/layer-specs.ts +64 -2
- package/src/capabilities/migrations.ts +9 -1
- package/src/capabilities/navigation-handler/navigation-handler.ts +20 -3
- package/src/capabilities/navigation-target-loader.ts +70 -0
- package/src/capabilities/react-context.tsx +20 -2
- package/src/capabilities/{react-surface.tsx → react-surface.ts} +14 -12
- package/src/capabilities/remote-trace-monitor.ts +62 -0
- package/src/capabilities/space-replication-progress.ts +143 -0
- package/src/capabilities/trace-progress.ts +84 -0
- package/src/commands/account/login/login.ts +48 -6
- package/src/commands/account/logout/logout.ts +4 -0
- package/src/commands/halo/index.ts +6 -2
- package/src/commands/halo/share/share.ts +16 -5
- package/src/commands/profile/create.ts +23 -40
- package/src/containers/AccountContainer/AccountContainer.tsx +6 -5
- package/src/containers/DevicesContainer/DevicesContainer.tsx +2 -0
- package/src/containers/InvitationsContainer/InvitationsContainer.tsx +2 -0
- package/src/containers/JoinDialog/JoinDialog.tsx +2 -0
- package/src/containers/ProfileContainer/ProfileContainer.tsx +19 -13
- package/src/containers/RecoveryCodeDialog/RecoveryCodeDialog.tsx +2 -0
- package/src/containers/RecoveryCredentialsContainer/RecoveryCredentialsContainer.tsx +7 -9
- package/src/containers/ResetDialog/ResetDialog.tsx +2 -0
- package/src/containers/UsageContainer/UsageContainer.tsx +10 -1
- package/src/containers/UsageContainer/UsageView.stories.tsx +0 -12
- package/src/containers/UsageContainer/UsageView.tsx +9 -10
- package/src/halo-services-layer.ts +29 -0
- package/src/index.ts +9 -0
- package/src/operations/definitions.ts +9 -1
- package/src/operations/errors.test.ts +27 -0
- package/src/operations/errors.ts +47 -0
- package/src/operations/index.ts +3 -0
- package/src/operations/open-usage.ts +3 -3
- package/src/operations/redeem-passkey.ts +85 -55
- package/src/operations/resolve-navigation-targets.ts +71 -0
- package/src/operations/share-identity.ts +3 -3
- package/src/operations/update-profile.ts +20 -0
- package/src/progress/index.ts +5 -0
- package/src/progress/progress-keys.ts +15 -0
- package/src/testing/initializeIdentity.ts +10 -2
- package/src/translations.ts +2 -0
- package/src/types/capabilities.ts +15 -1
- package/src/types/schema.ts +7 -0
- package/dist/lib/neutral/AccountContainer-7SF53UON.mjs +0 -186
- package/dist/lib/neutral/AccountContainer-7SF53UON.mjs.map +0 -7
- package/dist/lib/neutral/ClientPlugin.mjs +0 -72
- package/dist/lib/neutral/ClientPlugin.mjs.map +0 -7
- package/dist/lib/neutral/ClientPlugin.node.mjs +0 -1156
- package/dist/lib/neutral/ClientPlugin.node.mjs.map +0 -7
- package/dist/lib/neutral/ClientPlugin.workerd.mjs +0 -16
- package/dist/lib/neutral/ClientPlugin.workerd.mjs.map +0 -7
- package/dist/lib/neutral/DevicesContainer-PRWIN36N.mjs +0 -271
- package/dist/lib/neutral/DevicesContainer-PRWIN36N.mjs.map +0 -7
- package/dist/lib/neutral/InvitationsContainer-BI5RAWET.mjs +0 -143
- package/dist/lib/neutral/InvitationsContainer-BI5RAWET.mjs.map +0 -7
- package/dist/lib/neutral/JoinDialog-4BWV4CYB.mjs +0 -53
- package/dist/lib/neutral/JoinDialog-4BWV4CYB.mjs.map +0 -7
- package/dist/lib/neutral/ProfileContainer-YEAYOTX5.mjs +0 -169
- package/dist/lib/neutral/ProfileContainer-YEAYOTX5.mjs.map +0 -7
- package/dist/lib/neutral/RecoveryCodeDialog-7EPNKCLB.mjs +0 -59
- package/dist/lib/neutral/RecoveryCodeDialog-7EPNKCLB.mjs.map +0 -7
- package/dist/lib/neutral/RecoveryCredentialsContainer-6BZ2IWX7.mjs +0 -60
- package/dist/lib/neutral/RecoveryCredentialsContainer-6BZ2IWX7.mjs.map +0 -7
- package/dist/lib/neutral/ResetDialog-KUWX45JY.mjs +0 -57
- package/dist/lib/neutral/ResetDialog-KUWX45JY.mjs.map +0 -7
- package/dist/lib/neutral/UsageContainer-2DWCVVE4.mjs +0 -241
- package/dist/lib/neutral/UsageContainer-2DWCVVE4.mjs.map +0 -7
- package/dist/lib/neutral/account-cache-YVQKLNV2.mjs.map +0 -7
- package/dist/lib/neutral/app-graph-builder-RVXTD6OE.mjs +0 -159
- package/dist/lib/neutral/app-graph-builder-RVXTD6OE.mjs.map +0 -7
- package/dist/lib/neutral/capabilities/index.mjs +0 -34
- package/dist/lib/neutral/capabilities/index.mjs.map +0 -7
- package/dist/lib/neutral/capabilities/node.mjs +0 -21
- package/dist/lib/neutral/capabilities/node.mjs.map +0 -7
- package/dist/lib/neutral/chunk-6G4KZLBG.mjs.map +0 -7
- package/dist/lib/neutral/chunk-7DEIKHB7.mjs +0 -199
- package/dist/lib/neutral/chunk-7DEIKHB7.mjs.map +0 -7
- package/dist/lib/neutral/chunk-A7WDDIWY.mjs +0 -162
- package/dist/lib/neutral/chunk-A7WDDIWY.mjs.map +0 -7
- package/dist/lib/neutral/chunk-GSKMAS3S.mjs.map +0 -7
- package/dist/lib/neutral/chunk-J5LGTIGS.mjs +0 -10
- package/dist/lib/neutral/chunk-J5LGTIGS.mjs.map +0 -7
- package/dist/lib/neutral/chunk-JY35S2CN.mjs +0 -27
- package/dist/lib/neutral/chunk-JY35S2CN.mjs.map +0 -7
- package/dist/lib/neutral/chunk-ZFABGG2E.mjs +0 -8
- package/dist/lib/neutral/chunk-ZFABGG2E.mjs.map +0 -7
- package/dist/lib/neutral/client-7I5Y5SOA.mjs +0 -62
- package/dist/lib/neutral/client-7I5Y5SOA.mjs.map +0 -7
- package/dist/lib/neutral/components/index.mjs +0 -1
- package/dist/lib/neutral/components/index.mjs.map +0 -7
- package/dist/lib/neutral/containers/index.mjs +0 -25
- package/dist/lib/neutral/containers/index.mjs.map +0 -7
- package/dist/lib/neutral/create-agent-6UKJMZS5.mjs +0 -26
- package/dist/lib/neutral/create-agent-6UKJMZS5.mjs.map +0 -7
- package/dist/lib/neutral/create-identity-ULCRB3YH.mjs +0 -42
- package/dist/lib/neutral/create-identity-ULCRB3YH.mjs.map +0 -7
- package/dist/lib/neutral/create-passkey-I7VDS3AC.mjs +0 -81
- package/dist/lib/neutral/create-passkey-I7VDS3AC.mjs.map +0 -7
- package/dist/lib/neutral/create-recovery-code-DH2B6EGP.mjs +0 -36
- package/dist/lib/neutral/create-recovery-code-DH2B6EGP.mjs.map +0 -7
- package/dist/lib/neutral/hub-http-client-WOJUCDKV.mjs +0 -19
- package/dist/lib/neutral/hub-http-client-WOJUCDKV.mjs.map +0 -7
- package/dist/lib/neutral/index.mjs +0 -25
- package/dist/lib/neutral/index.mjs.map +0 -7
- package/dist/lib/neutral/join-identity-PJCHDNLH.mjs +0 -27
- package/dist/lib/neutral/join-identity-PJCHDNLH.mjs.map +0 -7
- package/dist/lib/neutral/layer-specs-YI7BVWKZ.mjs +0 -59
- package/dist/lib/neutral/layer-specs-YI7BVWKZ.mjs.map +0 -7
- package/dist/lib/neutral/meta.json +0 -1
- package/dist/lib/neutral/meta.mjs +0 -8
- package/dist/lib/neutral/meta.mjs.map +0 -7
- package/dist/lib/neutral/migrations-7FTW55ER.mjs +0 -23
- package/dist/lib/neutral/migrations-7FTW55ER.mjs.map +0 -7
- package/dist/lib/neutral/navigation-handler-MQ6MZXLX.mjs +0 -46
- package/dist/lib/neutral/navigation-handler-MQ6MZXLX.mjs.map +0 -7
- package/dist/lib/neutral/open-usage-OJVTPGOY.mjs +0 -27
- package/dist/lib/neutral/open-usage-OJVTPGOY.mjs.map +0 -7
- package/dist/lib/neutral/operation-handler-E3HB7E2T.mjs +0 -13
- package/dist/lib/neutral/operation-handler-E3HB7E2T.mjs.map +0 -7
- package/dist/lib/neutral/operations/index.mjs +0 -12
- package/dist/lib/neutral/operations/index.mjs.map +0 -7
- package/dist/lib/neutral/plugin.mjs +0 -17
- package/dist/lib/neutral/plugin.mjs.map +0 -7
- package/dist/lib/neutral/react-context-V74T6JOJ.mjs +0 -23
- package/dist/lib/neutral/react-context-V74T6JOJ.mjs.map +0 -7
- package/dist/lib/neutral/react-surface-HPXRA65U.mjs +0 -75
- package/dist/lib/neutral/react-surface-HPXRA65U.mjs.map +0 -7
- package/dist/lib/neutral/recover-identity-B7YM2BR4.mjs +0 -26
- package/dist/lib/neutral/recover-identity-B7YM2BR4.mjs.map +0 -7
- package/dist/lib/neutral/redeem-passkey-TYP4XLHO.mjs +0 -66
- package/dist/lib/neutral/redeem-passkey-TYP4XLHO.mjs.map +0 -7
- package/dist/lib/neutral/redeem-token-2J33R3PV.mjs +0 -29
- package/dist/lib/neutral/redeem-token-2J33R3PV.mjs.map +0 -7
- package/dist/lib/neutral/reset-storage-K47HZTGP.mjs +0 -26
- package/dist/lib/neutral/reset-storage-K47HZTGP.mjs.map +0 -7
- package/dist/lib/neutral/schema-defs-IHBCKTMM.mjs +0 -51
- package/dist/lib/neutral/schema-defs-IHBCKTMM.mjs.map +0 -7
- package/dist/lib/neutral/share-identity-TOROBLWL.mjs +0 -31
- package/dist/lib/neutral/share-identity-TOROBLWL.mjs.map +0 -7
- package/dist/lib/neutral/testing/index.mjs +0 -25
- package/dist/lib/neutral/testing/index.mjs.map +0 -7
- package/dist/lib/neutral/translations.mjs +0 -124
- package/dist/lib/neutral/translations.mjs.map +0 -7
- package/dist/lib/neutral/types/index.mjs +0 -16
- package/dist/lib/neutral/types/index.mjs.map +0 -7
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import * as Effect from 'effect/Effect';
|
|
6
|
-
import
|
|
6
|
+
import { type ComponentProps } from 'react';
|
|
7
7
|
|
|
8
8
|
import { Capabilities, Capability } from '@dxos/app-framework';
|
|
9
9
|
import { Surface } from '@dxos/app-framework/ui';
|
|
@@ -36,37 +36,39 @@ export default Capability.makeModule(
|
|
|
36
36
|
Surface.create({
|
|
37
37
|
id: Account.Profile,
|
|
38
38
|
filter: AppSurface.literal(AppSurface.Article, Account.Profile),
|
|
39
|
-
component:
|
|
39
|
+
component: ProfileContainer,
|
|
40
40
|
}),
|
|
41
41
|
Surface.create({
|
|
42
42
|
id: Account.Devices,
|
|
43
43
|
filter: AppSurface.literal(AppSurface.Article, Account.Devices),
|
|
44
|
-
component:
|
|
44
|
+
component: DevicesContainer,
|
|
45
|
+
props: () => ({ createInvitationUrl }),
|
|
45
46
|
}),
|
|
46
47
|
Surface.create({
|
|
47
48
|
id: Account.Security,
|
|
48
49
|
filter: AppSurface.literal(AppSurface.Article, Account.Security),
|
|
49
|
-
component:
|
|
50
|
+
component: RecoveryCredentialsContainer,
|
|
50
51
|
}),
|
|
51
52
|
Surface.create({
|
|
52
53
|
id: Account.Account,
|
|
53
54
|
filter: AppSurface.literal(AppSurface.Article, Account.Account),
|
|
54
|
-
component:
|
|
55
|
+
component: AccountContainer,
|
|
55
56
|
}),
|
|
56
57
|
Surface.create({
|
|
57
58
|
id: Account.Invitations,
|
|
58
59
|
filter: AppSurface.literal(AppSurface.Article, Account.Invitations),
|
|
59
|
-
component:
|
|
60
|
+
component: InvitationsContainer,
|
|
60
61
|
}),
|
|
61
62
|
Surface.create({
|
|
62
63
|
id: Account.Usage,
|
|
63
64
|
filter: AppSurface.literal(AppSurface.Article, Account.Usage),
|
|
64
|
-
component:
|
|
65
|
+
component: UsageContainer,
|
|
65
66
|
}),
|
|
66
67
|
Surface.create({
|
|
67
68
|
id: JOIN_DIALOG,
|
|
68
69
|
filter: AppSurface.component<ComponentProps<typeof JoinDialog>>(AppSurface.Dialog, JOIN_DIALOG),
|
|
69
|
-
component:
|
|
70
|
+
component: JoinDialog,
|
|
71
|
+
props: ({ data: { props } }) => ({ ...props }),
|
|
70
72
|
}),
|
|
71
73
|
Surface.create({
|
|
72
74
|
id: RECOVERY_CODE_DIALOG,
|
|
@@ -74,14 +76,14 @@ export default Capability.makeModule(
|
|
|
74
76
|
AppSurface.Dialog,
|
|
75
77
|
RECOVERY_CODE_DIALOG,
|
|
76
78
|
),
|
|
77
|
-
component:
|
|
79
|
+
component: RecoveryCodeDialog,
|
|
80
|
+
props: ({ data: { props } }) => ({ ...props }),
|
|
78
81
|
}),
|
|
79
82
|
Surface.create({
|
|
80
83
|
id: RESET_DIALOG,
|
|
81
84
|
filter: AppSurface.component<Pick<ComponentProps<typeof ResetDialog>, 'mode'>>(AppSurface.Dialog, RESET_DIALOG),
|
|
82
|
-
component:
|
|
83
|
-
|
|
84
|
-
),
|
|
85
|
+
component: ResetDialog,
|
|
86
|
+
props: ({ data: { props } }) => ({ ...props, onReset, capabilityManager }),
|
|
85
87
|
}),
|
|
86
88
|
]);
|
|
87
89
|
}),
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import * as Effect from 'effect/Effect';
|
|
6
|
+
import * as Option from 'effect/Option';
|
|
7
|
+
import * as Stream from 'effect/Stream';
|
|
8
|
+
|
|
9
|
+
import { Capabilities, Capability } from '@dxos/app-framework';
|
|
10
|
+
import { RemoteTraceMonitor } from '@dxos/compute-runtime';
|
|
11
|
+
|
|
12
|
+
import { ClientCapabilities } from '#types';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Contributes a swarm-backed {@link Capabilities.RemoteTraceMonitor} (DX-1125). Remote runtimes
|
|
16
|
+
* (edge intrinsics / function-invoker) broadcast their ephemeral trace messages over the space swarm;
|
|
17
|
+
* this monitor subscribes via the client's network service and decodes them so the aggregate
|
|
18
|
+
* {@link Process.Monitor.subscribeToTraceMessages} surfaces remote progress.
|
|
19
|
+
*
|
|
20
|
+
* The client is resolved lazily inside the subscribe closure (invoked only when a consumer
|
|
21
|
+
* subscribes, well after `ClientReady`), so this module can be collected at `SetupProcessManager`
|
|
22
|
+
* before the client capability exists.
|
|
23
|
+
*/
|
|
24
|
+
export default Capability.makeModule(
|
|
25
|
+
Effect.fnUntraced(function* () {
|
|
26
|
+
const capabilityManager = yield* Capability.Service;
|
|
27
|
+
|
|
28
|
+
const monitor = RemoteTraceMonitor.createSwarmRemoteTraceMonitor({
|
|
29
|
+
subscribe: (tags) =>
|
|
30
|
+
// Empty tag set matches nothing (avoids a firehose) — skip the subscription entirely.
|
|
31
|
+
tags.length === 0
|
|
32
|
+
? Stream.empty
|
|
33
|
+
: Stream.unwrap(
|
|
34
|
+
Effect.sync(() => {
|
|
35
|
+
const client = capabilityManager.getAll(ClientCapabilities.Client)[0];
|
|
36
|
+
if (!client) {
|
|
37
|
+
return Stream.empty;
|
|
38
|
+
}
|
|
39
|
+
// The subscribing peer is nominal for broadcasts: the edge keys the subscription off
|
|
40
|
+
// the WebSocket connection, not this object; it only affects point-to-point filtering.
|
|
41
|
+
const peer = {
|
|
42
|
+
peerKey:
|
|
43
|
+
client.halo.device?.deviceKey.toHex() ?? client.halo.identity.get()?.identityKey.toHex() ?? '',
|
|
44
|
+
};
|
|
45
|
+
return client.services.rpc.NetworkService.subscribeMessages({ peer, tags }).pipe(
|
|
46
|
+
// Carry the envelope tags with the payload — the wire payload drops ref meta
|
|
47
|
+
// (`trigger`), and decode restores it from the tags for cancel addressing.
|
|
48
|
+
Stream.filterMap((message) =>
|
|
49
|
+
message.payload?.value
|
|
50
|
+
? Option.some({ payload: message.payload.value, tags: message.tags })
|
|
51
|
+
: Option.none(),
|
|
52
|
+
),
|
|
53
|
+
// Never fail the aggregate monitor stream on a transient network error.
|
|
54
|
+
Stream.catchAll(() => Stream.empty),
|
|
55
|
+
);
|
|
56
|
+
}),
|
|
57
|
+
),
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
return Capability.contributes(Capabilities.RemoteTraceMonitor, monitor);
|
|
61
|
+
}),
|
|
62
|
+
);
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import * as Effect from 'effect/Effect';
|
|
6
|
+
import * as Fiber from 'effect/Fiber';
|
|
7
|
+
import * as Scope from 'effect/Scope';
|
|
8
|
+
import * as Stream from 'effect/Stream';
|
|
9
|
+
|
|
10
|
+
import { Capabilities, Capability } from '@dxos/app-framework';
|
|
11
|
+
import { AppCapabilities } from '@dxos/app-toolkit';
|
|
12
|
+
import { type Space, SpaceState } from '@dxos/client/echo';
|
|
13
|
+
import { ServiceResolver } from '@dxos/compute';
|
|
14
|
+
import { Database } from '@dxos/echo';
|
|
15
|
+
|
|
16
|
+
import { ClientCapabilities } from '#types';
|
|
17
|
+
|
|
18
|
+
import { createSpaceFeedReplicationProgressKey, createSpaceReplicationProgressKey } from '../progress';
|
|
19
|
+
|
|
20
|
+
type MonitorUpdate = {
|
|
21
|
+
readonly label: string;
|
|
22
|
+
readonly current: number;
|
|
23
|
+
readonly total: number;
|
|
24
|
+
readonly note?: string;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Publishes per-space replication backlog — automerge documents and ECHO feed blocks — into the
|
|
29
|
+
* {@link AppCapabilities.ProgressRegistry}. Subscribes to the combined sync-state stream and drops
|
|
30
|
+
* monitors once a space catches up.
|
|
31
|
+
*/
|
|
32
|
+
export default Capability.makeModule(
|
|
33
|
+
Effect.fnUntraced(function* () {
|
|
34
|
+
const client = yield* Capability.get(ClientCapabilities.Client);
|
|
35
|
+
const registry = yield* Capability.get(AppCapabilities.ProgressRegistry);
|
|
36
|
+
const processManagerRuntime = yield* Capability.get(Capabilities.ProcessManagerRuntime);
|
|
37
|
+
|
|
38
|
+
const monitors = new Map<string, AppCapabilities.ProgressMonitor>();
|
|
39
|
+
|
|
40
|
+
yield* Effect.addFinalizer(() =>
|
|
41
|
+
Effect.sync(() => {
|
|
42
|
+
for (const monitor of monitors.values()) {
|
|
43
|
+
monitor.remove();
|
|
44
|
+
}
|
|
45
|
+
monitors.clear();
|
|
46
|
+
}),
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
const applyMonitor = (key: string, update: MonitorUpdate | undefined): void => {
|
|
50
|
+
if (update === undefined) {
|
|
51
|
+
monitors.get(key)?.remove();
|
|
52
|
+
monitors.delete(key);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
let monitor = monitors.get(key);
|
|
57
|
+
if (!monitor) {
|
|
58
|
+
monitor = registry.register(key, { label: update.label, total: update.total });
|
|
59
|
+
monitors.set(key, monitor);
|
|
60
|
+
}
|
|
61
|
+
monitor.set(update.current);
|
|
62
|
+
monitor.total(update.total);
|
|
63
|
+
if (update.note !== undefined) {
|
|
64
|
+
monitor.note(update.note);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
// A space that has not finished initializing throws from its `properties` getter, and the
|
|
69
|
+
// spaces subscription fires before initialization completes (startup, space creation) — so
|
|
70
|
+
// the name is read lazily per sync-state update, and only once the space is SPACE_READY.
|
|
71
|
+
const getSpaceName = (space: Space): string | undefined =>
|
|
72
|
+
space.state.get() === SpaceState.SPACE_READY ? space.properties.name : undefined;
|
|
73
|
+
|
|
74
|
+
const runtime = yield* Effect.runtime<Scope.Scope>();
|
|
75
|
+
const subscribeSpace = (space: Space): void =>
|
|
76
|
+
void Effect.gen(function* () {
|
|
77
|
+
const fiber = processManagerRuntime.runFork(
|
|
78
|
+
Database.subscribeToSyncState().pipe(
|
|
79
|
+
Stream.runForEach(
|
|
80
|
+
Effect.fnUntraced(function* (state) {
|
|
81
|
+
const name = getSpaceName(space);
|
|
82
|
+
applyMonitor(createSpaceReplicationProgressKey(space.id), toDocumentUpdate(name, state));
|
|
83
|
+
applyMonitor(createSpaceFeedReplicationProgressKey(space.id), toFeedUpdate(name, state));
|
|
84
|
+
}),
|
|
85
|
+
),
|
|
86
|
+
Effect.provide(ServiceResolver.provide({ space: space.id }, Database.Service)),
|
|
87
|
+
),
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
yield* Effect.addFinalizer(() => Fiber.interrupt(fiber));
|
|
91
|
+
}).pipe(Effect.provide(runtime), Effect.runFork);
|
|
92
|
+
|
|
93
|
+
const spacesSubscription = client.spaces.subscribe((spaces) => {
|
|
94
|
+
for (const space of spaces) {
|
|
95
|
+
subscribeSpace(space);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
yield* Effect.addFinalizer(() => Effect.sync(() => spacesSubscription.unsubscribe()));
|
|
99
|
+
for (const space of client.spaces.get()) {
|
|
100
|
+
subscribeSpace(space);
|
|
101
|
+
}
|
|
102
|
+
}),
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
/** Derives the automerge document monitor state, or `undefined` when caught up. */
|
|
106
|
+
const toDocumentUpdate = (name: string | undefined, state: Database.SyncState): MonitorUpdate | undefined => {
|
|
107
|
+
const unsynced = state.unsyncedDocumentCount;
|
|
108
|
+
if (unsynced === 0) {
|
|
109
|
+
return undefined;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const total = state.totalDocumentCount > 0 ? state.totalDocumentCount : unsynced;
|
|
113
|
+
return {
|
|
114
|
+
label: getSpaceProgressLabel(name ?? 'Space', 'CRDTs'),
|
|
115
|
+
current: Math.max(0, total - unsynced),
|
|
116
|
+
total,
|
|
117
|
+
};
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
/** Derives the ECHO feed block monitor state, or `undefined` when caught up. */
|
|
121
|
+
const toFeedUpdate = (name: string | undefined, state: Database.SyncState): MonitorUpdate | undefined => {
|
|
122
|
+
const blocksToPull = Number(state.blocksToPull);
|
|
123
|
+
const blocksToPush = Number(state.blocksToPush);
|
|
124
|
+
const pending = blocksToPull + blocksToPush;
|
|
125
|
+
if (pending === 0) {
|
|
126
|
+
return undefined;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const totalBlocks = Number(state.totalBlocks);
|
|
130
|
+
const total = totalBlocks > 0 ? totalBlocks : pending;
|
|
131
|
+
return {
|
|
132
|
+
label: getSpaceProgressLabel(name ?? 'Space', 'Feeds'),
|
|
133
|
+
current: Math.max(0, total - pending),
|
|
134
|
+
total,
|
|
135
|
+
note: `↓${blocksToPull} ↑${blocksToPush}`,
|
|
136
|
+
};
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
/** Human label for a space progress monitor. */
|
|
140
|
+
const getSpaceProgressLabel = (name: string | undefined, suffix?: string): string => {
|
|
141
|
+
const name_ = name ?? 'Space';
|
|
142
|
+
return suffix ? `${name_} · ${suffix}` : name_;
|
|
143
|
+
};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import * as Effect from 'effect/Effect';
|
|
6
|
+
import * as Fiber from 'effect/Fiber';
|
|
7
|
+
import * as Stream from 'effect/Stream';
|
|
8
|
+
|
|
9
|
+
import { Capabilities, Capability } from '@dxos/app-framework';
|
|
10
|
+
import { AppCapabilities, type CancelTarget, createProgressTraceSink, resolveTriggerId } from '@dxos/app-toolkit';
|
|
11
|
+
import { Trace } from '@dxos/compute';
|
|
12
|
+
import { RemoteProcessManager } from '@dxos/compute-runtime';
|
|
13
|
+
import { log } from '@dxos/log';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Projects remote (edge-runtime) `status.update` trace events into the {@link AppCapabilities.ProgressRegistry}
|
|
17
|
+
* (DX-1125). Subscribes to the aggregate {@link Process.Monitor.subscribeToTraceMessages}, whose remote
|
|
18
|
+
* source is the swarm-backed monitor contributed by `remote-trace-monitor`.
|
|
19
|
+
*
|
|
20
|
+
* Only edge-runtime messages are projected here: local progress already flows through the
|
|
21
|
+
* `plugin-progress` trace sink, and both write the same progress keys — projecting local messages
|
|
22
|
+
* twice would let two writers clobber each other's registry handles.
|
|
23
|
+
*
|
|
24
|
+
* Cancel on this path always routes to {@link RemoteProcessManager} (edge) — local terminate is
|
|
25
|
+
* handled by the `plugin-progress` sink, which never sees these messages.
|
|
26
|
+
*/
|
|
27
|
+
export default Capability.makeModule(
|
|
28
|
+
Effect.fnUntraced(function* () {
|
|
29
|
+
const capabilityManager = yield* Capability.Service;
|
|
30
|
+
const monitor = yield* Capability.get(Capabilities.ProcessMonitor);
|
|
31
|
+
const processManagerRuntime = yield* Capability.get(Capabilities.ProcessManagerRuntime);
|
|
32
|
+
const resolver = yield* Capability.get(Capabilities.ServiceResolver);
|
|
33
|
+
|
|
34
|
+
// Edge-only cancel. Soft-fails (the meter has already cleared locally), but never silently: an
|
|
35
|
+
// unresolvable manager or a rejected request means the run may still be going on the edge.
|
|
36
|
+
const cancelRemote = (space: string, trigger: string, pid?: string) =>
|
|
37
|
+
Effect.runFork(
|
|
38
|
+
resolver.resolve(RemoteProcessManager.Service, {}).pipe(
|
|
39
|
+
Effect.flatMap((manager) => manager.cancel?.({ space, trigger, pid }) ?? Effect.void),
|
|
40
|
+
Effect.scoped,
|
|
41
|
+
Effect.catchAllCause((cause) =>
|
|
42
|
+
Effect.sync(() => log.warn('edge progress cancel failed', { space, trigger, pid, cause })),
|
|
43
|
+
),
|
|
44
|
+
),
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
const progressSink = createProgressTraceSink(() => capabilityManager.getAll(AppCapabilities.ProgressRegistry)[0], {
|
|
48
|
+
// An edge run is a chain of bounded invocations, each with a fresh pid, so a pid tombstone
|
|
49
|
+
// would only mask one chain link and the next would resurrect the meter — suppress the key
|
|
50
|
+
// until the run's terminal status, matching the local (single-pid) cancel behaviour.
|
|
51
|
+
cancelScope: 'run',
|
|
52
|
+
cancelProcess: (target: CancelTarget) => {
|
|
53
|
+
const triggerId = resolveTriggerId(target);
|
|
54
|
+
if (target.space && triggerId) {
|
|
55
|
+
cancelRemote(target.space, triggerId, target.pid);
|
|
56
|
+
} else {
|
|
57
|
+
// Never drop a user's cancel silently — an unresolvable target means the trace meta lost
|
|
58
|
+
// its addressing (e.g. the swarm wire codec), which must surface in the log.
|
|
59
|
+
log.warn('edge progress cancel dropped: unresolvable target', {
|
|
60
|
+
space: target.space,
|
|
61
|
+
trigger: target.trigger?.uri.toString(),
|
|
62
|
+
pid: target.pid,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// TODO(mykola): Possible bug source. Use `Effect.forkDaemon`.
|
|
69
|
+
const fiber = processManagerRuntime.runFork(
|
|
70
|
+
monitor.subscribeToTraceMessages({ type: Trace.StatusUpdate.key }).pipe(
|
|
71
|
+
Stream.runForEach((message) =>
|
|
72
|
+
Effect.sync(() => {
|
|
73
|
+
const runtimeName = message.meta.runtimeName;
|
|
74
|
+
if (runtimeName && Trace.isEdgeRuntime(runtimeName)) {
|
|
75
|
+
progressSink.write(message);
|
|
76
|
+
}
|
|
77
|
+
}),
|
|
78
|
+
),
|
|
79
|
+
),
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
yield* Effect.addFinalizer(() => Fiber.interrupt(fiber));
|
|
83
|
+
}),
|
|
84
|
+
);
|
|
@@ -11,6 +11,7 @@ import * as Effect from 'effect/Effect';
|
|
|
11
11
|
import * as Match from 'effect/Match';
|
|
12
12
|
import * as Option from 'effect/Option';
|
|
13
13
|
|
|
14
|
+
import { Capabilities, Plugin } from '@dxos/app-framework';
|
|
14
15
|
import { CommandConfig, performRecoveryOAuthFlow, print } from '@dxos/cli-util';
|
|
15
16
|
import { type Client, ClientService } from '@dxos/client';
|
|
16
17
|
import { Invitation, InvitationEncoder } from '@dxos/client/invitations';
|
|
@@ -19,6 +20,8 @@ import { HubHttpClient } from '@dxos/edge-client';
|
|
|
19
20
|
import { invariant } from '@dxos/invariant';
|
|
20
21
|
import { ATPROTO_OAUTH_SCOPES, OAuthProvider } from '@dxos/protocols';
|
|
21
22
|
|
|
23
|
+
import { ClientOperation } from '#operations';
|
|
24
|
+
|
|
22
25
|
import { printIdentity, waitForState } from '../../halo/util';
|
|
23
26
|
|
|
24
27
|
type LoginMethod = 'email' | 'atproto' | 'device-invitation' | 'recovery-code';
|
|
@@ -56,6 +59,8 @@ export const login = Command.make(
|
|
|
56
59
|
Effect.fn(function* ({ method, input }) {
|
|
57
60
|
const { json } = yield* CommandConfig;
|
|
58
61
|
const client = yield* ClientService;
|
|
62
|
+
const manager = yield* Plugin.Service;
|
|
63
|
+
const { invoke } = manager.capabilities.get(Capabilities.OperationInvoker);
|
|
59
64
|
// TODO(wittjosiah): How to surface this error to the user cleanly?
|
|
60
65
|
invariant(!client.halo.identity.get(), 'Already logged in. Run `dx account logout` first.');
|
|
61
66
|
|
|
@@ -69,7 +74,7 @@ export const login = Command.make(
|
|
|
69
74
|
|
|
70
75
|
const identity = yield* Match.value(resolvedMethod).pipe(
|
|
71
76
|
Match.when('atproto', () => loginWithAtproto(client, resolvedInput)),
|
|
72
|
-
Match.when('email', () => loginWithEmail(client, resolvedInput)),
|
|
77
|
+
Match.when('email', () => loginWithEmail(client, resolvedInput, invoke)),
|
|
73
78
|
Match.when('recovery-code', () => loginWithRecoveryCode(client, resolvedInput)),
|
|
74
79
|
Match.when('device-invitation', () => loginWithDeviceInvitation(client, resolvedInput)),
|
|
75
80
|
Match.exhaustive,
|
|
@@ -108,16 +113,53 @@ const loginWithRecoveryCode = (client: Client, recoveryCode: string) =>
|
|
|
108
113
|
Effect.tryPromise(() => client.halo.recoverIdentity({ recoveryCode }));
|
|
109
114
|
|
|
110
115
|
/**
|
|
111
|
-
* Email login
|
|
112
|
-
*
|
|
116
|
+
* Email login, mirroring the gate's login tab (`WelcomeScreen.handleLogin`). Hub-service answers in
|
|
117
|
+
* one of three ways:
|
|
118
|
+
*
|
|
119
|
+
* - `needsIdentity`: the address may bind a fresh Account but has no identity yet. Create one
|
|
120
|
+
* locally and retry with its DID; the hub then admits it directly — there is no token because
|
|
121
|
+
* there is nothing to recover — and we provision the agent as the gate does.
|
|
122
|
+
* - `token`: an Account exists and the hub returned a one-time recovery token inline.
|
|
123
|
+
* - neither: the link went out by email, so prompt for the token from the message.
|
|
113
124
|
*/
|
|
114
|
-
const loginWithEmail = (client: Client, email: string) =>
|
|
125
|
+
const loginWithEmail = (client: Client, email: string, invoke: Capabilities.OperationInvoker['invoke']) =>
|
|
115
126
|
Effect.gen(function* () {
|
|
116
127
|
const hubUrl = client.config.values?.runtime?.app?.env?.DX_HUB_URL;
|
|
117
128
|
invariant(hubUrl, 'Hub URL not configured (runtime.app.env.DX_HUB_URL).');
|
|
118
129
|
const hub = new HubHttpClient(hubUrl);
|
|
119
|
-
const
|
|
120
|
-
|
|
130
|
+
const result = yield* Effect.tryPromise(() => hub.login(DxContext.default(), { email }));
|
|
131
|
+
|
|
132
|
+
if (result.needsIdentity) {
|
|
133
|
+
// `CreateIdentity` fires `IdentityCreated`, which is what provisions the personal space.
|
|
134
|
+
yield* invoke(ClientOperation.CreateIdentity, { displayName: email.split('@')[0] });
|
|
135
|
+
const identity = client.halo.identity.get();
|
|
136
|
+
invariant(identity, 'identity should exist after create');
|
|
137
|
+
// The local identity outlives any failure from here on, and the `Already logged in` guard
|
|
138
|
+
// above rejects a plain retry, so a rejected request and a non-admitting response both need
|
|
139
|
+
// the same recovery guidance.
|
|
140
|
+
const notAdmitted = (detail: string) =>
|
|
141
|
+
new Error(
|
|
142
|
+
`Hub did not admit ${email} (${detail}). A local identity was created and remains bound to ` +
|
|
143
|
+
'this profile; run `dx account logout` to clear it before retrying.',
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
const retry = yield* Effect.tryPromise({
|
|
147
|
+
try: () =>
|
|
148
|
+
hub.login(DxContext.default(), {
|
|
149
|
+
email,
|
|
150
|
+
identityDid: identity.did,
|
|
151
|
+
identityKey: identity.identityKey.toHex(),
|
|
152
|
+
}),
|
|
153
|
+
catch: (cause) => notAdmitted(cause instanceof Error ? cause.message : String(cause)),
|
|
154
|
+
});
|
|
155
|
+
if (!retry.admitted) {
|
|
156
|
+
return yield* Effect.fail(notAdmitted('no admission granted'));
|
|
157
|
+
}
|
|
158
|
+
yield* invoke(ClientOperation.CreateAgent);
|
|
159
|
+
return identity;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
let token = result.token;
|
|
121
163
|
if (!token) {
|
|
122
164
|
yield* Console.log(`A login link was sent to ${email}. Paste the token from the email below.`);
|
|
123
165
|
token = yield* Prompt.text({ message: 'Login token' }).pipe(Prompt.run);
|
|
@@ -40,6 +40,10 @@ export const logout = Command.make(
|
|
|
40
40
|
() => Effect.void,
|
|
41
41
|
),
|
|
42
42
|
);
|
|
43
|
+
// Recreate the (now empty) data root: the client's SQLite storage opens a file inside it
|
|
44
|
+
// without creating the directory first, so leaving it absent makes every later command fail
|
|
45
|
+
// with "unable to open database file" — including the login this logout exists to enable.
|
|
46
|
+
yield* fs.makeDirectory(path, { recursive: true });
|
|
43
47
|
if (json) {
|
|
44
48
|
yield* Console.log(JSON.stringify({ profile, loggedOut: true }, null, 2));
|
|
45
49
|
} else {
|
|
@@ -4,18 +4,22 @@
|
|
|
4
4
|
|
|
5
5
|
import * as Command from '@effect/cli/Command';
|
|
6
6
|
|
|
7
|
+
import { create } from './create';
|
|
7
8
|
import { credential } from './credential';
|
|
8
9
|
import { identity } from './identity';
|
|
9
10
|
import { keys } from './keys';
|
|
10
11
|
import { seed } from './seed';
|
|
12
|
+
import { share } from './share';
|
|
11
13
|
import { update } from './update';
|
|
12
14
|
|
|
13
15
|
// `create`, `join`, and `recover` are superseded by `dx account login`, which logs in to an
|
|
14
16
|
// existing identity via the same methods as Composer (email / atproto / device-invitation /
|
|
15
17
|
// recovery-code). Note: `join` was omitted and the `device-invitation` login method may hang —
|
|
16
|
-
// both rely on p2p networking which does not work in bun.
|
|
18
|
+
// both rely on p2p networking which does not work in bun. `create` and `share` are registered
|
|
19
|
+
// for the CLI-first pairing flow (CLI hosts the device invitation; the browser joins), which
|
|
20
|
+
// runs over the edge messenger rather than raw p2p.
|
|
17
21
|
|
|
18
22
|
export const halo: Command.Command<any, any, any, any> = Command.make('halo').pipe(
|
|
19
23
|
Command.withDescription('Manage HALO identity.'),
|
|
20
|
-
Command.withSubcommands([credential, identity, keys, seed, update]),
|
|
24
|
+
Command.withSubcommands([create, credential, identity, keys, seed, share, update]),
|
|
21
25
|
);
|
|
@@ -24,6 +24,13 @@ export const handler = Effect.fn(function* ({
|
|
|
24
24
|
const { json } = yield* CommandConfig;
|
|
25
25
|
const client = yield* ClientService;
|
|
26
26
|
|
|
27
|
+
// Validate up front — an invalid host inside `onConnecting` would abort after the invitation
|
|
28
|
+
// is already hosted, without printing the codes.
|
|
29
|
+
yield* Effect.try({
|
|
30
|
+
try: () => new URL(host),
|
|
31
|
+
catch: () => new Error(`--host must be an absolute URL: ${host}`),
|
|
32
|
+
});
|
|
33
|
+
|
|
27
34
|
// Always use persistent and delegated (auth required) due to P2P limitations
|
|
28
35
|
const observable = client.halo.share({
|
|
29
36
|
authMethod: Invitation.AuthMethod.SHARED_SECRET,
|
|
@@ -42,16 +49,20 @@ export const handler = Effect.fn(function* ({
|
|
|
42
49
|
// Copy auth code to clipboard
|
|
43
50
|
yield* copyToClipboard(authCode).pipe(Effect.catchAll(() => Effect.void));
|
|
44
51
|
|
|
52
|
+
const url = new URL(host);
|
|
53
|
+
url.searchParams.set('deviceInvitationCode', invitationCode);
|
|
54
|
+
|
|
45
55
|
if (!json) {
|
|
46
56
|
yield* Console.log(`\nSecret: ${authCode} (copied to clipboard)\n`);
|
|
57
|
+
yield* Console.log(`\nInvitation: ${invitationCode}\n`);
|
|
58
|
+
// Print the joinable URL even when not opening so it can be pasted manually.
|
|
59
|
+
yield* Console.log(`\nURL: ${url.toString()}\n`);
|
|
47
60
|
}
|
|
48
61
|
|
|
49
62
|
if (open) {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
} else if (!json) {
|
|
54
|
-
yield* Console.log(`\nInvitation: ${invitationCode}\n`);
|
|
63
|
+
yield* openBrowser(url.toString()).pipe(
|
|
64
|
+
Effect.catchAll(() => Console.error(`Failed to open browser: ${url.toString()}`)),
|
|
65
|
+
);
|
|
55
66
|
}
|
|
56
67
|
}),
|
|
57
68
|
},
|
|
@@ -17,47 +17,30 @@ import { trim } from '@dxos/util';
|
|
|
17
17
|
|
|
18
18
|
import { printProfileCreated } from './util';
|
|
19
19
|
|
|
20
|
+
// `edgeFeatures` must match Composer's defaults (see composer-app/dx.yml): without
|
|
21
|
+
// `signaling: true` the client silently falls back to an isolated in-memory signal manager and
|
|
22
|
+
// device invitations hang at "Connecting…" (host and guest never meet in the swarm).
|
|
23
|
+
const makeTemplate = (edgeUrl: string) => trim`
|
|
24
|
+
version: 1
|
|
25
|
+
runtime:
|
|
26
|
+
client:
|
|
27
|
+
storage:
|
|
28
|
+
persistent: true
|
|
29
|
+
edgeFeatures:
|
|
30
|
+
signaling: true
|
|
31
|
+
subductionReplicator: true
|
|
32
|
+
feedReplicator: true
|
|
33
|
+
agents: true
|
|
34
|
+
services:
|
|
35
|
+
edge:
|
|
36
|
+
url: ${edgeUrl}
|
|
37
|
+
`;
|
|
38
|
+
|
|
20
39
|
const TEMPLATES = {
|
|
21
|
-
default:
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
storage:
|
|
26
|
-
persistent: true
|
|
27
|
-
services:
|
|
28
|
-
edge:
|
|
29
|
-
url: https://edge-production.dxos.workers.dev
|
|
30
|
-
`,
|
|
31
|
-
main: trim`
|
|
32
|
-
version: 1
|
|
33
|
-
runtime:
|
|
34
|
-
client:
|
|
35
|
-
storage:
|
|
36
|
-
persistent: true
|
|
37
|
-
services:
|
|
38
|
-
edge:
|
|
39
|
-
url: https://edge-main.dxos.workers.dev
|
|
40
|
-
`,
|
|
41
|
-
dev: trim`
|
|
42
|
-
version: 1
|
|
43
|
-
runtime:
|
|
44
|
-
client:
|
|
45
|
-
storage:
|
|
46
|
-
persistent: true
|
|
47
|
-
services:
|
|
48
|
-
edge:
|
|
49
|
-
url: https://edge.dxos.workers.dev
|
|
50
|
-
`,
|
|
51
|
-
local: trim`
|
|
52
|
-
version: 1
|
|
53
|
-
runtime:
|
|
54
|
-
client:
|
|
55
|
-
storage:
|
|
56
|
-
persistent: true
|
|
57
|
-
services:
|
|
58
|
-
edge:
|
|
59
|
-
url: http://localhost:8787
|
|
60
|
-
`,
|
|
40
|
+
default: makeTemplate('https://edge-production.dxos.workers.dev'),
|
|
41
|
+
main: makeTemplate('https://edge-main.dxos.workers.dev'),
|
|
42
|
+
dev: makeTemplate('https://edge.dxos.workers.dev'),
|
|
43
|
+
local: makeTemplate('http://localhost:8787'),
|
|
61
44
|
} as const;
|
|
62
45
|
|
|
63
46
|
export const create = Command.make(
|
|
@@ -8,8 +8,7 @@ import React, { type FormEvent, useCallback, useState } from 'react';
|
|
|
8
8
|
import { useCapability, useOperationInvoker } from '@dxos/app-framework/ui';
|
|
9
9
|
import { LayoutOperation } from '@dxos/app-toolkit';
|
|
10
10
|
import { Context } from '@dxos/context';
|
|
11
|
-
import {
|
|
12
|
-
import { useIdentity } from '@dxos/react-client/halo';
|
|
11
|
+
import { useIdentity } from '@dxos/halo-react';
|
|
13
12
|
import { Button, Icon, IconButton, Input, Message, useAsyncEffect, useTranslation } from '@dxos/react-ui';
|
|
14
13
|
import { Form } from '@dxos/react-ui-form';
|
|
15
14
|
|
|
@@ -81,7 +80,7 @@ export const AccountContainer = () => {
|
|
|
81
80
|
return;
|
|
82
81
|
}
|
|
83
82
|
try {
|
|
84
|
-
const identityDid = identity
|
|
83
|
+
const identityDid = identity?.did;
|
|
85
84
|
await hubHttp.requestAccess(new Context(), { email, identityDid });
|
|
86
85
|
} catch {
|
|
87
86
|
// Surface a generic confirmation; failure details would leak signal.
|
|
@@ -122,7 +121,7 @@ export const AccountContainer = () => {
|
|
|
122
121
|
<>
|
|
123
122
|
<Message.Root valence='warning'>
|
|
124
123
|
<Message.Title icon='ph--warning--duotone'>{t('no-edge-access.title')}</Message.Title>
|
|
125
|
-
<Message.
|
|
124
|
+
<Message.Body>{t('no-edge-access.description')}</Message.Body>
|
|
126
125
|
</Message.Root>
|
|
127
126
|
<Form.Row label={t('request-access.label')} description={t('request-access.description')}>
|
|
128
127
|
{requestSubmitted ? (
|
|
@@ -149,7 +148,7 @@ export const AccountContainer = () => {
|
|
|
149
148
|
) : accountState === 'error' && !account ? (
|
|
150
149
|
<Message.Root valence='error'>
|
|
151
150
|
<Message.Title icon='ph--cloud-x--duotone'>{t('account-offline.title')}</Message.Title>
|
|
152
|
-
<Message.
|
|
151
|
+
<Message.Body>{t('account-offline.description')}</Message.Body>
|
|
153
152
|
</Message.Root>
|
|
154
153
|
) : account ? (
|
|
155
154
|
<>
|
|
@@ -181,3 +180,5 @@ export const AccountContainer = () => {
|
|
|
181
180
|
</Form.Root>
|
|
182
181
|
);
|
|
183
182
|
};
|
|
183
|
+
|
|
184
|
+
AccountContainer.displayName = 'AccountContainer';
|