@dxos/plugin-client 0.12.0-next-73daef452f1464b62efdbca75fb0067c1066f264 → 0.13.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/Account.mjs +29 -10
- package/dist/lib/Account.mjs.map +1 -1
- package/dist/lib/CliLogin.mjs +78 -0
- package/dist/lib/CliLogin.mjs.map +1 -0
- package/dist/lib/ClientCapabilities.mjs +25 -1
- package/dist/lib/ClientCapabilities.mjs.map +1 -1
- package/dist/lib/ClientEvents.mjs +7 -3
- package/dist/lib/ClientEvents.mjs.map +1 -1
- package/dist/lib/{chunk-definitions.mjs → ClientOperation.mjs} +11 -7
- package/dist/lib/ClientOperation.mjs.map +1 -0
- package/dist/lib/ClientOptions.mjs.map +1 -1
- package/dist/lib/PasskeyError.mjs +69 -12
- package/dist/lib/PasskeyError.mjs.map +1 -1
- package/dist/lib/capabilities.browser.mjs +134 -0
- package/dist/lib/capabilities.browser.mjs.map +1 -0
- package/dist/lib/capabilities.mjs +47 -10
- package/dist/lib/capabilities.mjs.map +1 -1
- package/dist/lib/capabilities.node.mjs +40 -7
- package/dist/lib/capabilities.node.mjs.map +1 -1
- package/dist/lib/capabilities.tauri.mjs +134 -0
- package/dist/lib/capabilities.tauri.mjs.map +1 -0
- package/dist/lib/capabilities.workerd.mjs +24 -4
- package/dist/lib/capabilities.workerd.mjs.map +1 -1
- package/dist/lib/chunk-AccountContainer.mjs +53 -41
- package/dist/lib/chunk-AccountContainer.mjs.map +1 -1
- package/dist/lib/chunk-CliLoginDialog.mjs +146 -0
- package/dist/lib/chunk-CliLoginDialog.mjs.map +1 -0
- package/dist/lib/chunk-ContactPickerContainer.mjs +120 -0
- package/dist/lib/chunk-ContactPickerContainer.mjs.map +1 -0
- package/dist/lib/chunk-ContactsContainer.mjs +53 -0
- package/dist/lib/chunk-ContactsContainer.mjs.map +1 -0
- package/dist/lib/chunk-DevicesContainer.mjs +48 -112
- package/dist/lib/chunk-DevicesContainer.mjs.map +1 -1
- package/dist/lib/chunk-HaloServices.mjs +28 -0
- package/dist/lib/chunk-HaloServices.mjs.map +1 -0
- package/dist/lib/chunk-InvitationsContainer.mjs +61 -39
- package/dist/lib/chunk-InvitationsContainer.mjs.map +1 -1
- package/dist/lib/chunk-JoinDialog.mjs +10 -9
- package/dist/lib/chunk-JoinDialog.mjs.map +1 -1
- package/dist/lib/chunk-ProfileContainer.mjs +60 -39
- package/dist/lib/chunk-ProfileContainer.mjs.map +1 -1
- package/dist/lib/chunk-RecoveryCodeDialog.mjs +26 -21
- package/dist/lib/chunk-RecoveryCodeDialog.mjs.map +1 -1
- package/dist/lib/chunk-RecoveryCredentialsContainer.mjs +95 -65
- package/dist/lib/chunk-RecoveryCredentialsContainer.mjs.map +1 -1
- package/dist/lib/chunk-ResetDialog.mjs +26 -14
- package/dist/lib/chunk-ResetDialog.mjs.map +1 -1
- package/dist/lib/chunk-SpaceInvitationContainer.mjs +50 -0
- package/dist/lib/chunk-SpaceInvitationContainer.mjs.map +1 -0
- package/dist/lib/chunk-UsageContainer.mjs +22 -20
- package/dist/lib/chunk-UsageContainer.mjs.map +1 -1
- package/dist/lib/chunk-account-cache.mjs +2 -2
- package/dist/lib/chunk-account-cache.mjs.map +1 -1
- package/dist/lib/chunk-app-graph-builder.mjs +159 -60
- package/dist/lib/chunk-app-graph-builder.mjs.map +1 -1
- package/dist/lib/chunk-client-services.mjs +21 -0
- package/dist/lib/chunk-client-services.mjs.map +1 -0
- package/dist/lib/chunk-client.mjs +27 -20
- package/dist/lib/chunk-client.mjs.map +1 -1
- package/dist/lib/chunk-constants.mjs +2 -1
- package/dist/lib/chunk-constants.mjs.map +1 -1
- package/dist/lib/chunk-create-agent.mjs +1 -1
- package/dist/lib/chunk-create-agent.mjs.map +1 -1
- package/dist/lib/chunk-create-identity.mjs +2 -2
- package/dist/lib/chunk-create-identity.mjs.map +1 -1
- package/dist/lib/chunk-create-passkey.mjs +49 -40
- package/dist/lib/chunk-create-passkey.mjs.map +1 -1
- package/dist/lib/chunk-create-recovery-code.mjs +2 -2
- package/dist/lib/chunk-create-recovery-code.mjs.map +1 -1
- package/dist/lib/chunk-grant-service-access.mjs +1 -1
- package/dist/lib/chunk-grant-service-access.mjs.map +1 -1
- package/dist/lib/chunk-halo.mjs +414 -0
- package/dist/lib/chunk-halo.mjs.map +1 -0
- package/dist/lib/chunk-identity-lifecycle.mjs +74 -0
- package/dist/lib/chunk-identity-lifecycle.mjs.map +1 -0
- package/dist/lib/chunk-join-identity.mjs +2 -2
- package/dist/lib/chunk-join-identity.mjs.map +1 -1
- package/dist/lib/chunk-layer-specs.mjs +72 -5
- package/dist/lib/chunk-layer-specs.mjs.map +1 -1
- package/dist/lib/chunk-navigation-handler.mjs +28 -5
- package/dist/lib/chunk-navigation-handler.mjs.map +1 -1
- package/dist/lib/chunk-navigation-target-loader.mjs +8 -9
- package/dist/lib/chunk-navigation-target-loader.mjs.map +1 -1
- package/dist/lib/chunk-open-usage.mjs +3 -3
- package/dist/lib/chunk-open-usage.mjs.map +1 -1
- package/dist/lib/chunk-react-context.mjs +5 -5
- package/dist/lib/chunk-react-context.mjs.map +1 -1
- package/dist/lib/chunk-react-surface.mjs +80 -64
- package/dist/lib/chunk-react-surface.mjs.map +1 -1
- package/dist/lib/chunk-recover-identity.mjs +2 -2
- package/dist/lib/chunk-recover-identity.mjs.map +1 -1
- package/dist/lib/chunk-redeem-passkey.mjs +7 -5
- package/dist/lib/chunk-redeem-passkey.mjs.map +1 -1
- package/dist/lib/chunk-redeem-token.mjs +1 -1
- package/dist/lib/chunk-redeem-token.mjs.map +1 -1
- package/dist/lib/chunk-remote-trace-monitor.mjs +3 -2
- package/dist/lib/chunk-remote-trace-monitor.mjs.map +1 -1
- package/dist/lib/chunk-reset-storage.mjs +6 -3
- package/dist/lib/chunk-reset-storage.mjs.map +1 -1
- package/dist/lib/chunk-resolve-navigation-targets.mjs +3 -3
- package/dist/lib/chunk-resolve-navigation-targets.mjs.map +1 -1
- package/dist/lib/chunk-revoke-recovery-credential.mjs +1 -1
- package/dist/lib/chunk-revoke-recovery-credential.mjs.map +1 -1
- package/dist/lib/chunk-share-identity.mjs +2 -2
- package/dist/lib/chunk-share-identity.mjs.map +1 -1
- package/dist/lib/chunk-space-replication-progress.mjs +49 -7
- package/dist/lib/chunk-space-replication-progress.mjs.map +1 -1
- package/dist/lib/chunk-trace-progress.mjs +5 -5
- package/dist/lib/chunk-trace-progress.mjs.map +1 -1
- package/dist/lib/chunk-update-profile.mjs +1 -1
- package/dist/lib/chunk-update-profile.mjs.map +1 -1
- package/dist/lib/chunk-useAccountUrl.mjs +23 -0
- package/dist/lib/chunk-useAccountUrl.mjs.map +1 -0
- package/dist/lib/chunk-useHubClient.mjs +30 -0
- package/dist/lib/chunk-useHubClient.mjs.map +1 -0
- package/dist/lib/commands.mjs +1 -1
- package/dist/lib/commands.mjs.map +1 -1
- package/dist/lib/commands.node.mjs +771 -1
- package/dist/lib/commands.node.mjs.map +1 -1
- package/dist/lib/components.mjs +91 -0
- package/dist/lib/components.mjs.map +1 -0
- package/dist/lib/containers.mjs +5 -1
- package/dist/lib/containers.mjs.map +1 -1
- package/dist/lib/index.mjs +2 -27
- package/dist/lib/meta.mjs.map +1 -1
- package/dist/lib/ns/HaloServices.mjs +2 -0
- package/dist/lib/operations.mjs +3 -3
- package/dist/lib/operations.mjs.map +1 -1
- package/dist/lib/plugin.mjs +2 -2
- package/dist/lib/plugin.mjs.map +1 -1
- package/dist/lib/testing.mjs +71 -2
- package/dist/lib/testing.mjs.map +1 -1
- package/dist/lib/translations.mjs +26 -5
- package/dist/lib/translations.mjs.map +1 -1
- package/dist/lib/types.mjs +3 -1
- package/dist/types/src/HaloServices.d.ts +2 -0
- package/dist/types/src/HaloServices.d.ts.map +1 -0
- package/dist/types/src/capabilities/client-services.d.ts +9 -0
- package/dist/types/src/capabilities/client-services.d.ts.map +1 -0
- package/dist/types/src/capabilities/client.d.ts +33 -2
- package/dist/types/src/capabilities/client.d.ts.map +1 -1
- package/dist/types/src/capabilities/commands.d.ts +1 -1
- package/dist/types/src/capabilities/commands.d.ts.map +1 -1
- package/dist/types/src/capabilities/commands.node.d.ts +1 -1
- package/dist/types/src/capabilities/commands.node.d.ts.map +1 -1
- package/dist/types/src/capabilities/gen/browser.d.ts +45 -0
- package/dist/types/src/capabilities/gen/browser.d.ts.map +1 -0
- package/dist/types/src/capabilities/gen/node.d.ts +3 -1
- package/dist/types/src/capabilities/gen/node.d.ts.map +1 -1
- package/dist/types/src/capabilities/gen/tauri.d.ts +45 -0
- package/dist/types/src/capabilities/gen/tauri.d.ts.map +1 -0
- package/dist/types/src/capabilities/gen/workerd.d.ts +2 -0
- package/dist/types/src/capabilities/gen/workerd.d.ts.map +1 -1
- package/dist/types/src/capabilities/identity-lifecycle.d.ts +14 -0
- package/dist/types/src/capabilities/identity-lifecycle.d.ts.map +1 -0
- package/dist/types/src/capabilities/index.d.ts +5 -3
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/navigation-handler/index.d.ts +1 -1
- package/dist/types/src/capabilities/navigation-handler/index.d.ts.map +1 -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 +1 -6
- package/dist/types/src/capabilities/navigation-target-loader.d.ts.map +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts +2 -2
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
- package/dist/types/src/capabilities/remote-trace-monitor.d.ts +1 -1
- package/dist/types/src/capabilities/remote-trace-monitor.d.ts.map +1 -1
- package/dist/types/src/capabilities/trace-progress.d.ts +2 -2
- package/dist/types/src/commands/account/index.d.ts +1 -1
- package/dist/types/src/commands/account/index.d.ts.map +1 -1
- package/dist/types/src/commands/account/invitation/create/create.d.ts +4 -3
- package/dist/types/src/commands/account/invitation/create/create.d.ts.map +1 -1
- package/dist/types/src/commands/account/invitation/create/index.d.ts +1 -1
- package/dist/types/src/commands/account/invitation/create/index.d.ts.map +1 -1
- package/dist/types/src/commands/account/invitation/index.d.ts +2 -2
- package/dist/types/src/commands/account/invitation/index.d.ts.map +1 -1
- package/dist/types/src/commands/account/login/index.d.ts +1 -1
- package/dist/types/src/commands/account/login/index.d.ts.map +1 -1
- package/dist/types/src/commands/account/login/login.d.ts +6 -5
- package/dist/types/src/commands/account/login/login.d.ts.map +1 -1
- package/dist/types/src/commands/account/logout/index.d.ts +1 -1
- package/dist/types/src/commands/account/logout/index.d.ts.map +1 -1
- package/dist/types/src/commands/account/logout/logout.d.ts +2 -2
- package/dist/types/src/commands/account/logout/logout.d.ts.map +1 -1
- package/dist/types/src/commands/account/signup/index.d.ts +1 -1
- package/dist/types/src/commands/account/signup/index.d.ts.map +1 -1
- package/dist/types/src/commands/account/signup/signup.d.ts +5 -4
- package/dist/types/src/commands/account/signup/signup.d.ts.map +1 -1
- package/dist/types/src/commands/account/util.d.ts +1 -1
- package/dist/types/src/commands/account/util.d.ts.map +1 -1
- package/dist/types/src/commands/config/index.d.ts +1 -1
- package/dist/types/src/commands/config/index.d.ts.map +1 -1
- package/dist/types/src/commands/config/view.d.ts +1 -1
- package/dist/types/src/commands/config/view.d.ts.map +1 -1
- package/dist/types/src/commands/device/index.d.ts +1 -1
- package/dist/types/src/commands/device/index.d.ts.map +1 -1
- package/dist/types/src/commands/device/info/index.d.ts +1 -1
- package/dist/types/src/commands/device/info/index.d.ts.map +1 -1
- package/dist/types/src/commands/device/info/info.d.ts +1 -1
- package/dist/types/src/commands/device/info/info.d.ts.map +1 -1
- package/dist/types/src/commands/device/list/index.d.ts +1 -1
- package/dist/types/src/commands/device/list/index.d.ts.map +1 -1
- package/dist/types/src/commands/device/list/list.d.ts +1 -1
- package/dist/types/src/commands/device/list/list.d.ts.map +1 -1
- package/dist/types/src/commands/device/update/index.d.ts +1 -1
- package/dist/types/src/commands/device/update/index.d.ts.map +1 -1
- package/dist/types/src/commands/device/update/update.d.ts +1 -1
- package/dist/types/src/commands/device/update/update.d.ts.map +1 -1
- package/dist/types/src/commands/device/util.d.ts +1 -1
- package/dist/types/src/commands/device/util.d.ts.map +1 -1
- package/dist/types/src/commands/edge/index.d.ts +1 -1
- package/dist/types/src/commands/edge/index.d.ts.map +1 -1
- package/dist/types/src/commands/edge/status.d.ts +1 -1
- package/dist/types/src/commands/edge/status.d.ts.map +1 -1
- package/dist/types/src/commands/errors.d.ts +33 -0
- package/dist/types/src/commands/errors.d.ts.map +1 -0
- package/dist/types/src/commands/halo/credential/add/add.d.ts +5 -4
- package/dist/types/src/commands/halo/credential/add/add.d.ts.map +1 -1
- package/dist/types/src/commands/halo/credential/add/index.d.ts +1 -1
- package/dist/types/src/commands/halo/credential/add/index.d.ts.map +1 -1
- package/dist/types/src/commands/halo/credential/index.d.ts +2 -2
- package/dist/types/src/commands/halo/credential/index.d.ts.map +1 -1
- package/dist/types/src/commands/halo/credential/list/index.d.ts +1 -1
- package/dist/types/src/commands/halo/credential/list/index.d.ts.map +1 -1
- package/dist/types/src/commands/halo/credential/list/list.d.ts +1 -1
- package/dist/types/src/commands/halo/credential/list/list.d.ts.map +1 -1
- package/dist/types/src/commands/halo/identity/identity.d.ts +1 -1
- package/dist/types/src/commands/halo/identity/identity.d.ts.map +1 -1
- package/dist/types/src/commands/halo/identity/index.d.ts +1 -1
- package/dist/types/src/commands/halo/identity/index.d.ts.map +1 -1
- package/dist/types/src/commands/halo/index.d.ts +1 -1
- package/dist/types/src/commands/halo/index.d.ts.map +1 -1
- package/dist/types/src/commands/halo/keys/index.d.ts +1 -1
- package/dist/types/src/commands/halo/keys/index.d.ts.map +1 -1
- package/dist/types/src/commands/halo/keys/keys.d.ts +1 -1
- package/dist/types/src/commands/halo/keys/keys.d.ts.map +1 -1
- package/dist/types/src/commands/halo/seed/index.d.ts +1 -1
- package/dist/types/src/commands/halo/seed/index.d.ts.map +1 -1
- package/dist/types/src/commands/halo/seed/seed.d.ts +1 -1
- package/dist/types/src/commands/halo/seed/seed.d.ts.map +1 -1
- package/dist/types/src/commands/halo/share/index.d.ts +1 -1
- package/dist/types/src/commands/halo/share/index.d.ts.map +1 -1
- package/dist/types/src/commands/halo/share/share.d.ts +4 -3
- package/dist/types/src/commands/halo/share/share.d.ts.map +1 -1
- package/dist/types/src/commands/halo/update/index.d.ts +1 -1
- package/dist/types/src/commands/halo/update/index.d.ts.map +1 -1
- package/dist/types/src/commands/halo/update/update.d.ts +1 -1
- package/dist/types/src/commands/halo/update/update.d.ts.map +1 -1
- package/dist/types/src/commands/halo/util.d.ts +2 -2
- package/dist/types/src/commands/halo/util.d.ts.map +1 -1
- package/dist/types/src/commands/index.d.ts +6 -6
- package/dist/types/src/commands/index.d.ts.map +1 -1
- package/dist/types/src/commands/profile/create.d.ts +1 -1
- package/dist/types/src/commands/profile/create.d.ts.map +1 -1
- package/dist/types/src/commands/profile/delete.d.ts +1 -1
- package/dist/types/src/commands/profile/delete.d.ts.map +1 -1
- package/dist/types/src/commands/profile/import.d.ts +5 -4
- package/dist/types/src/commands/profile/import.d.ts.map +1 -1
- package/dist/types/src/commands/profile/index.d.ts +2 -2
- package/dist/types/src/commands/profile/index.d.ts.map +1 -1
- package/dist/types/src/commands/profile/inspect.d.ts +1 -1
- package/dist/types/src/commands/profile/inspect.d.ts.map +1 -1
- package/dist/types/src/commands/profile/list.d.ts +1 -1
- package/dist/types/src/commands/profile/list.d.ts.map +1 -1
- package/dist/types/src/commands/profile/reset.d.ts +2 -2
- package/dist/types/src/commands/profile/reset.d.ts.map +1 -1
- package/dist/types/src/components/DevicesForm/DevicesForm.d.ts +19 -0
- package/dist/types/src/components/DevicesForm/DevicesForm.d.ts.map +1 -0
- package/dist/types/src/components/DevicesForm/DevicesForm.stories.d.ts +207 -0
- package/dist/types/src/components/DevicesForm/DevicesForm.stories.d.ts.map +1 -0
- package/dist/types/src/components/DevicesForm/index.d.ts +2 -0
- package/dist/types/src/components/DevicesForm/index.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +1 -0
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/constants.d.ts +1 -0
- package/dist/types/src/constants.d.ts.map +1 -1
- package/dist/types/src/containers/AccountContainer/AccountContainer.stories.d.ts +1 -1
- package/dist/types/src/containers/AccountContainer/AccountContainer.stories.d.ts.map +1 -1
- package/dist/types/src/containers/AccountContainer/index.d.ts +1 -1
- package/dist/types/src/containers/AccountContainer/index.d.ts.map +1 -1
- package/dist/types/src/containers/CliLoginDialog/CliLoginDialog.d.ts +12 -0
- package/dist/types/src/containers/CliLoginDialog/CliLoginDialog.d.ts.map +1 -0
- package/dist/types/src/containers/CliLoginDialog/index.d.ts +4 -0
- package/dist/types/src/containers/CliLoginDialog/index.d.ts.map +1 -0
- package/dist/types/src/containers/ContactPickerContainer/ContactPickerContainer.d.ts +8 -0
- package/dist/types/src/containers/ContactPickerContainer/ContactPickerContainer.d.ts.map +1 -0
- package/dist/types/src/containers/ContactPickerContainer/ContactPickerContainer.stories.d.ts +206 -0
- package/dist/types/src/containers/ContactPickerContainer/ContactPickerContainer.stories.d.ts.map +1 -0
- package/dist/types/src/containers/ContactPickerContainer/index.d.ts +2 -0
- package/dist/types/src/containers/ContactPickerContainer/index.d.ts.map +1 -0
- package/dist/types/src/containers/ContactsContainer/ContactsContainer.d.ts +3 -0
- package/dist/types/src/containers/ContactsContainer/ContactsContainer.d.ts.map +1 -0
- package/dist/types/src/containers/ContactsContainer/ContactsContainer.stories.d.ts +203 -0
- package/dist/types/src/containers/ContactsContainer/ContactsContainer.stories.d.ts.map +1 -0
- package/dist/types/src/containers/ContactsContainer/index.d.ts +2 -0
- package/dist/types/src/containers/ContactsContainer/index.d.ts.map +1 -0
- package/dist/types/src/containers/DevicesContainer/DevicesContainer.d.ts.map +1 -1
- package/dist/types/src/containers/DevicesContainer/DevicesContainer.stories.d.ts +19 -1
- package/dist/types/src/containers/DevicesContainer/DevicesContainer.stories.d.ts.map +1 -1
- package/dist/types/src/containers/DevicesContainer/index.d.ts +1 -1
- package/dist/types/src/containers/DevicesContainer/index.d.ts.map +1 -1
- package/dist/types/src/containers/InvitationsContainer/InvitationsContainer.stories.d.ts +1 -1
- package/dist/types/src/containers/InvitationsContainer/InvitationsContainer.stories.d.ts.map +1 -1
- package/dist/types/src/containers/InvitationsContainer/index.d.ts +1 -1
- package/dist/types/src/containers/InvitationsContainer/index.d.ts.map +1 -1
- package/dist/types/src/containers/JoinDialog/JoinDialog.d.ts.map +1 -1
- package/dist/types/src/containers/JoinDialog/JoinDialog.stories.d.ts +1 -1
- package/dist/types/src/containers/JoinDialog/JoinDialog.stories.d.ts.map +1 -1
- package/dist/types/src/containers/JoinDialog/index.d.ts +1 -1
- package/dist/types/src/containers/JoinDialog/index.d.ts.map +1 -1
- package/dist/types/src/containers/ProfileContainer/ProfileContainer.d.ts.map +1 -1
- package/dist/types/src/containers/ProfileContainer/ProfileContainer.stories.d.ts +1 -1
- package/dist/types/src/containers/ProfileContainer/ProfileContainer.stories.d.ts.map +1 -1
- package/dist/types/src/containers/ProfileContainer/index.d.ts +1 -1
- package/dist/types/src/containers/ProfileContainer/index.d.ts.map +1 -1
- package/dist/types/src/containers/RecoveryCodeDialog/RecoveryCodeDialog.d.ts.map +1 -1
- package/dist/types/src/containers/RecoveryCodeDialog/RecoveryCodeDialog.stories.d.ts.map +1 -1
- package/dist/types/src/containers/RecoveryCodeDialog/index.d.ts +2 -2
- package/dist/types/src/containers/RecoveryCodeDialog/index.d.ts.map +1 -1
- package/dist/types/src/containers/RecoveryCredentialsContainer/RecoveryCredentialsContainer.d.ts.map +1 -1
- package/dist/types/src/containers/RecoveryCredentialsContainer/RecoveryCredentialsContainer.stories.d.ts +1 -1
- package/dist/types/src/containers/RecoveryCredentialsContainer/RecoveryCredentialsContainer.stories.d.ts.map +1 -1
- package/dist/types/src/containers/RecoveryCredentialsContainer/index.d.ts +1 -1
- package/dist/types/src/containers/RecoveryCredentialsContainer/index.d.ts.map +1 -1
- package/dist/types/src/containers/ResetDialog/ResetDialog.d.ts +6 -7
- package/dist/types/src/containers/ResetDialog/ResetDialog.d.ts.map +1 -1
- package/dist/types/src/containers/ResetDialog/ResetDialog.stories.d.ts +2 -2
- package/dist/types/src/containers/ResetDialog/ResetDialog.stories.d.ts.map +1 -1
- package/dist/types/src/containers/ResetDialog/index.d.ts +2 -2
- package/dist/types/src/containers/ResetDialog/index.d.ts.map +1 -1
- package/dist/types/src/containers/SpaceInvitationContainer/SpaceInvitationContainer.d.ts +10 -0
- package/dist/types/src/containers/SpaceInvitationContainer/SpaceInvitationContainer.d.ts.map +1 -0
- package/dist/types/src/containers/SpaceInvitationContainer/index.d.ts +2 -0
- package/dist/types/src/containers/SpaceInvitationContainer/index.d.ts.map +1 -0
- package/dist/types/src/containers/UsageContainer/UsageView.d.ts.map +1 -1
- package/dist/types/src/containers/UsageContainer/UsageView.stories.d.ts +1 -1
- package/dist/types/src/containers/UsageContainer/UsageView.stories.d.ts.map +1 -1
- package/dist/types/src/containers/UsageContainer/index.d.ts +1 -1
- package/dist/types/src/containers/UsageContainer/index.d.ts.map +1 -1
- package/dist/types/src/containers/index.d.ts +9 -3
- package/dist/types/src/containers/index.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +2 -2
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +2 -5
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/operations/create-agent.d.ts +2 -2
- package/dist/types/src/operations/create-agent.d.ts.map +1 -1
- package/dist/types/src/operations/create-identity.d.ts +2 -2
- package/dist/types/src/operations/create-identity.d.ts.map +1 -1
- package/dist/types/src/operations/create-passkey.d.ts +2 -2
- package/dist/types/src/operations/create-passkey.d.ts.map +1 -1
- package/dist/types/src/operations/create-recovery-code.d.ts +2 -2
- package/dist/types/src/operations/create-recovery-code.d.ts.map +1 -1
- package/dist/types/src/operations/grant-service-access.d.ts +2 -2
- package/dist/types/src/operations/grant-service-access.d.ts.map +1 -1
- package/dist/types/src/operations/index.d.ts +1 -1
- package/dist/types/src/operations/index.d.ts.map +1 -1
- package/dist/types/src/operations/join-identity.d.ts +2 -2
- package/dist/types/src/operations/join-identity.d.ts.map +1 -1
- package/dist/types/src/operations/open-usage.d.ts +2 -2
- package/dist/types/src/operations/open-usage.d.ts.map +1 -1
- package/dist/types/src/operations/recover-identity.d.ts +2 -2
- package/dist/types/src/operations/recover-identity.d.ts.map +1 -1
- package/dist/types/src/operations/redeem-passkey.d.ts +2 -2
- package/dist/types/src/operations/redeem-passkey.d.ts.map +1 -1
- package/dist/types/src/operations/redeem-token.d.ts +2 -2
- package/dist/types/src/operations/redeem-token.d.ts.map +1 -1
- package/dist/types/src/operations/reset-storage.d.ts +2 -2
- package/dist/types/src/operations/reset-storage.d.ts.map +1 -1
- package/dist/types/src/operations/revoke-recovery-credential.d.ts +2 -2
- package/dist/types/src/operations/revoke-recovery-credential.d.ts.map +1 -1
- package/dist/types/src/operations/share-identity.d.ts +2 -2
- package/dist/types/src/operations/share-identity.d.ts.map +1 -1
- package/dist/types/src/operations/update-profile.d.ts +2 -2
- package/dist/types/src/operations/update-profile.d.ts.map +1 -1
- package/dist/types/src/plugin.d.ts.map +1 -1
- package/dist/types/src/progress/index.d.ts +2 -2
- package/dist/types/src/progress/index.d.ts.map +1 -1
- package/dist/types/src/progress/space-sync-progress.d.ts +10 -1
- package/dist/types/src/progress/space-sync-progress.d.ts.map +1 -1
- package/dist/types/src/testing/ClientPluginManager.d.ts +18 -0
- package/dist/types/src/testing/ClientPluginManager.d.ts.map +1 -0
- package/dist/types/src/testing/createFakeContacts.d.ts +16 -0
- package/dist/types/src/testing/createFakeContacts.d.ts.map +1 -0
- package/dist/types/src/testing/index.d.ts +4 -2
- package/dist/types/src/testing/index.d.ts.map +1 -1
- package/dist/types/src/testing/initializeIdentity.d.ts +1 -1
- package/dist/types/src/testing/initializeIdentity.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +2 -2
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/Account.d.ts +21 -7
- package/dist/types/src/types/Account.d.ts.map +1 -1
- package/dist/types/src/types/CliLogin.d.ts +33 -0
- package/dist/types/src/types/CliLogin.d.ts.map +1 -0
- package/dist/types/src/types/ClientCapabilities.d.ts +32 -3
- package/dist/types/src/types/ClientCapabilities.d.ts.map +1 -1
- package/dist/types/src/types/ClientEvents.d.ts +5 -1
- package/dist/types/src/types/ClientEvents.d.ts.map +1 -1
- package/dist/types/src/{operations/definitions.d.ts → types/ClientOperation.d.ts} +2 -1
- package/dist/types/src/types/ClientOperation.d.ts.map +1 -0
- package/dist/types/src/types/ClientOptions.d.ts +1 -8
- package/dist/types/src/types/ClientOptions.d.ts.map +1 -1
- package/dist/types/src/types/PasskeyError.d.ts +112 -11
- package/dist/types/src/types/PasskeyError.d.ts.map +1 -1
- package/dist/types/src/types/index.d.ts +9 -7
- package/dist/types/src/types/index.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +72 -61
- package/src/HaloServices.ts +7 -0
- package/src/capabilities/account-cache.ts +2 -2
- package/src/capabilities/app-graph-builder.ts +165 -69
- package/src/capabilities/client-services.ts +25 -0
- package/src/capabilities/client.ts +17 -12
- package/src/capabilities/commands.node.ts +1 -1
- package/src/capabilities/commands.ts +1 -1
- package/src/capabilities/gen/browser.ts +192 -0
- package/src/capabilities/gen/node.ts +48 -19
- package/src/capabilities/gen/tauri.ts +192 -0
- package/src/capabilities/gen/workerd.ts +41 -13
- package/src/capabilities/identity-lifecycle.ts +86 -0
- package/src/capabilities/index.ts +57 -26
- package/src/capabilities/layer-specs.ts +107 -4
- package/src/capabilities/navigation-handler/index.ts +2 -2
- package/src/capabilities/navigation-handler/navigation-handler.ts +20 -1
- package/src/capabilities/navigation-target-loader.ts +15 -10
- package/src/capabilities/react-context.tsx +2 -2
- package/src/capabilities/react-surface.ts +43 -18
- package/src/capabilities/remote-trace-monitor.ts +5 -2
- package/src/capabilities/schema-defs.test.ts +2 -2
- package/src/capabilities/space-replication-progress.ts +12 -7
- package/src/capabilities/trace-progress.ts +6 -6
- package/src/commands/account/index.ts +5 -5
- package/src/commands/account/invitation/create/create.ts +9 -5
- package/src/commands/account/invitation/create/index.ts +1 -1
- package/src/commands/account/invitation/index.ts +2 -2
- package/src/commands/account/login/index.ts +1 -1
- package/src/commands/account/login/login.ts +108 -37
- package/src/commands/account/logout/index.ts +1 -1
- package/src/commands/account/logout/logout.ts +8 -5
- package/src/commands/account/signup/index.ts +1 -1
- package/src/commands/account/signup/signup.ts +33 -19
- package/src/commands/account/util.test.ts +1 -1
- package/src/commands/account/util.ts +2 -2
- package/src/commands/config/index.ts +2 -2
- package/src/commands/config/view.ts +1 -1
- package/src/commands/device/index.ts +4 -4
- package/src/commands/device/info/index.ts +1 -1
- package/src/commands/device/info/info.test.ts +4 -3
- package/src/commands/device/info/info.ts +5 -4
- package/src/commands/device/list/index.ts +1 -1
- package/src/commands/device/list/list.test.ts +2 -2
- package/src/commands/device/list/list.ts +2 -2
- package/src/commands/device/update/index.ts +1 -1
- package/src/commands/device/update/update.ts +8 -9
- package/src/commands/device/util.ts +6 -5
- package/src/commands/edge/index.ts +2 -2
- package/src/commands/edge/status.ts +1 -1
- package/src/commands/errors.ts +8 -0
- package/src/commands/halo/credential/add/add.ts +13 -16
- package/src/commands/halo/credential/add/index.ts +1 -1
- package/src/commands/halo/credential/index.ts +3 -3
- package/src/commands/halo/credential/list/index.ts +1 -1
- package/src/commands/halo/credential/list/list.test.ts +2 -2
- package/src/commands/halo/credential/list/list.ts +15 -14
- package/src/commands/halo/identity/identity.test.ts +7 -3
- package/src/commands/halo/identity/identity.ts +2 -2
- package/src/commands/halo/identity/index.ts +1 -1
- package/src/commands/halo/index.ts +7 -7
- package/src/commands/halo/keys/index.ts +1 -1
- package/src/commands/halo/keys/keys.test.ts +5 -4
- package/src/commands/halo/keys/keys.ts +6 -5
- package/src/commands/halo/seed/index.ts +1 -1
- package/src/commands/halo/seed/seed.ts +1 -1
- package/src/commands/halo/share/index.ts +1 -1
- package/src/commands/halo/share/share.ts +15 -10
- package/src/commands/halo/update/index.ts +1 -1
- package/src/commands/halo/update/update.test.ts +2 -2
- package/src/commands/halo/update/update.ts +7 -17
- package/src/commands/halo/util.ts +11 -7
- package/src/commands/index.ts +6 -6
- package/src/commands/profile/create.ts +5 -5
- package/src/commands/profile/delete.ts +4 -4
- package/src/commands/profile/import.ts +17 -14
- package/src/commands/profile/index.ts +7 -7
- package/src/commands/profile/inspect.ts +9 -6
- package/src/commands/profile/list.ts +2 -2
- package/src/commands/profile/reset.ts +9 -6
- package/src/components/DevicesForm/DevicesForm.stories.tsx +62 -0
- package/src/components/DevicesForm/DevicesForm.tsx +100 -0
- package/src/components/DevicesForm/index.ts +5 -0
- package/src/components/index.ts +2 -0
- package/src/constants.ts +1 -0
- package/src/containers/AccountContainer/AccountContainer.stories.tsx +3 -3
- package/src/containers/AccountContainer/AccountContainer.tsx +54 -43
- package/src/containers/AccountContainer/index.ts +1 -1
- package/src/containers/CliLoginDialog/CliLoginDialog.tsx +159 -0
- package/src/containers/CliLoginDialog/index.ts +8 -0
- package/src/containers/ContactPickerContainer/ContactPickerContainer.stories.tsx +66 -0
- package/src/containers/ContactPickerContainer/ContactPickerContainer.tsx +126 -0
- package/src/containers/ContactPickerContainer/index.ts +5 -0
- package/src/containers/ContactsContainer/ContactsContainer.stories.tsx +48 -0
- package/src/containers/ContactsContainer/ContactsContainer.tsx +61 -0
- package/src/containers/ContactsContainer/index.ts +5 -0
- package/src/containers/DevicesContainer/DevicesContainer.stories.tsx +3 -3
- package/src/containers/DevicesContainer/DevicesContainer.tsx +45 -103
- package/src/containers/DevicesContainer/index.ts +1 -1
- package/src/containers/InvitationsContainer/InvitationsContainer.stories.tsx +3 -3
- package/src/containers/InvitationsContainer/InvitationsContainer.tsx +63 -60
- package/src/containers/InvitationsContainer/index.ts +1 -1
- package/src/containers/JoinDialog/JoinDialog.stories.tsx +5 -7
- package/src/containers/JoinDialog/JoinDialog.tsx +10 -9
- package/src/containers/JoinDialog/index.ts +1 -1
- package/src/containers/ProfileContainer/ProfileContainer.stories.tsx +3 -3
- package/src/containers/ProfileContainer/ProfileContainer.tsx +72 -55
- package/src/containers/ProfileContainer/index.ts +1 -1
- package/src/containers/RecoveryCodeDialog/RecoveryCodeDialog.stories.tsx +5 -6
- package/src/containers/RecoveryCodeDialog/RecoveryCodeDialog.tsx +27 -29
- package/src/containers/RecoveryCodeDialog/index.ts +2 -2
- package/src/containers/RecoveryCredentialsContainer/RecoveryCredentialsContainer.stories.tsx +7 -7
- package/src/containers/RecoveryCredentialsContainer/RecoveryCredentialsContainer.tsx +69 -41
- package/src/containers/RecoveryCredentialsContainer/index.ts +1 -1
- package/src/containers/ResetDialog/ResetDialog.stories.tsx +9 -21
- package/src/containers/ResetDialog/ResetDialog.tsx +35 -24
- package/src/containers/ResetDialog/index.ts +2 -2
- package/src/containers/SpaceInvitationContainer/SpaceInvitationContainer.tsx +62 -0
- package/src/containers/SpaceInvitationContainer/index.ts +8 -0
- package/src/containers/UsageContainer/UsageContainer.tsx +4 -4
- package/src/containers/UsageContainer/UsageView.stories.tsx +1 -1
- package/src/containers/UsageContainer/UsageView.tsx +22 -24
- package/src/containers/UsageContainer/index.ts +1 -1
- package/src/containers/index.ts +23 -12
- package/src/hooks/index.ts +2 -2
- package/src/hooks/useAccountUrl.ts +1 -1
- package/src/hooks/useHubClient.ts +3 -3
- package/src/index.ts +2 -5
- package/src/meta.ts +1 -1
- package/src/operations/create-agent.ts +2 -2
- package/src/operations/create-identity.ts +5 -3
- package/src/operations/create-passkey.ts +59 -37
- package/src/operations/create-recovery-code.ts +16 -15
- package/src/operations/grant-service-access.ts +9 -8
- package/src/operations/index.ts +17 -30
- package/src/operations/join-identity.ts +3 -3
- package/src/operations/open-usage.ts +3 -3
- package/src/operations/recover-identity.ts +3 -3
- package/src/operations/redeem-passkey.ts +63 -65
- package/src/operations/redeem-token.ts +2 -2
- package/src/operations/reset-storage.ts +4 -3
- package/src/operations/resolve-navigation-targets.ts +1 -1
- package/src/operations/revoke-recovery-credential.ts +9 -8
- package/src/operations/share-identity.ts +2 -2
- package/src/operations/update-profile.ts +2 -2
- package/src/plugin.test.ts +2 -2
- package/src/plugin.ts +30 -25
- package/src/progress/index.ts +2 -2
- package/src/progress/space-sync-progress.test.ts +36 -13
- package/src/progress/space-sync-progress.ts +21 -6
- package/src/schema-defs.test.ts +2 -2
- package/src/testing/ClientPluginManager.tsx +44 -0
- package/src/testing/createFakeContacts.ts +57 -0
- package/src/testing/index.ts +4 -2
- package/src/testing/initializeIdentity.ts +6 -2
- package/src/translations.ts +33 -9
- package/src/types/Account.ts +27 -11
- package/src/types/CliLogin.ts +78 -0
- package/src/types/ClientCapabilities.ts +38 -4
- package/src/types/ClientEvents.ts +5 -1
- package/src/{operations/definitions.ts → types/ClientOperation.ts} +5 -1
- package/src/types/ClientOptions.ts +3 -7
- package/src/types/PasskeyError.test.ts +96 -1
- package/src/types/PasskeyError.ts +85 -15
- package/src/types/index.ts +9 -7
- package/dist/lib/chunk-commands.mjs +0 -1090
- package/dist/lib/chunk-commands.mjs.map +0 -1
- package/dist/lib/chunk-definitions.mjs.map +0 -1
- package/dist/lib/chunk-hooks.mjs +0 -49
- package/dist/lib/chunk-hooks.mjs.map +0 -1
- package/dist/lib/chunk-progress.mjs +0 -35
- package/dist/lib/chunk-progress.mjs.map +0 -1
- package/dist/lib/index.mjs.map +0 -1
- package/dist/types/src/operations/definitions.d.ts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chunk-UsageContainer.mjs","names":[],"sources":["../../src/containers/UsageContainer/UsageView.tsx","../../src/containers/UsageContainer/UsageContainer.tsx"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Schema from 'effect/Schema';\nimport React, { useCallback, useMemo, useState } from 'react';\n\nimport { type GetProfileUsageResponse, type MeteringLimit, type MeteringUsageItem } from '@dxos/protocols';\nimport { Banner, Progress, useTranslation } from '@dxos/react-ui';\nimport { Form, type FormFieldProvider } from '@dxos/react-ui-form';\n\nimport { meta } from '#meta';\n\nexport type UsageViewState = 'loading' | 'ready' | 'error' | 'unavailable';\n\ntype UsageViewCommonProps = {\n /** Epoch milliseconds of the last successful fetch. */\n lastUpdated?: number;\n /** Invoked when the user requests a refresh. */\n onRefresh?: () => void;\n};\n\n/**\n * Discriminated on `state`: the payload is required (and only present) when `state` is `'ready'`, so a\n * missing payload can't be silently rendered as an empty plan.\n */\nexport type UsageViewProps =\n | (UsageViewCommonProps & { state: Exclude<UsageViewState, 'ready'>; data?: undefined })\n | (UsageViewCommonProps & { state: 'ready'; data: GetProfileUsageResponse });\n\ntype TFunction = (key: string, options?: Record<string, unknown>) => string;\n\n/**\n * Whether a usage row falls under a limit. Subtype segments are matched positionally against\n * `subtypePattern` where `*` matches any segment.\n */\nconst usageMatchesLimit = (item: MeteringUsageItem, limit: MeteringLimit): boolean => {\n if (item.eventType !== limit.eventType || item.valueKey !== limit.valueKey) {\n return false;\n }\n return limit.subtypePattern.every((pattern, index) => pattern === '*' || pattern === item.subtypePattern[index]);\n};\n\n/** Sum every usage item that falls under the limit. */\nconst sumUsageForLimit = (usage: GetProfileUsageResponse['usage'], limit: MeteringLimit): number =>\n usage.reduce((total, item) => (usageMatchesLimit(item, limit) ? total + item.amount : total), 0);\n\n/** Humanize a camelCase value key, e.g. `outputTokens` → `output tokens`. */\nconst formatValueKey = (valueKey: string): string =>\n valueKey\n .replace(/([A-Z])/g, ' $1')\n .trim()\n .toLowerCase();\n\n/**\n * Human label for a limit: a scope followed by the value key, e.g.\n * `{ eventType: 'ai', valueKey: 'outputTokens', subtypePattern: ['*'] }` → `All models · output tokens`,\n * `{ eventType: 'ai', valueKey: 'inputTokens', subtypePattern: ['claude-opus-4'] }` → `claude-opus-4 · input tokens`.\n */\nconst formatLimitLabel = (limit: MeteringLimit, t: TFunction): string => {\n const metric = formatValueKey(limit.valueKey);\n const subtype = limit.subtypePattern.filter((segment) => segment && segment !== '*').join('/');\n if (limit.eventType === 'ai') {\n return `${subtype || t('usage-all-models.label')} · ${metric}`;\n }\n return `${subtype ? `${limit.eventType}/${subtype}` : limit.eventType} · ${metric}`;\n};\n\nconst formatAmount = (amount: number): string => amount.toLocaleString();\n\nconst SECONDS_PER_HOUR = 60 * 60;\n\n/** Render `windowHours` as a localized \"N months / days / hours\" string. */\nconst formatWindow = (windowHours: number, t: TFunction): string => {\n if (windowHours % (24 * 30) === 0) {\n return t('usage-window-months.label', { count: windowHours / (24 * 30) });\n }\n if (windowHours % 24 === 0) {\n return t('usage-window-days.label', { count: windowHours / 24 });\n }\n return t('usage-window-hours.label', { count: windowHours });\n};\n\ntype UsageRow = {\n key: string;\n /** Field label (schema `title` annotation). */\n label: string;\n /** Field caption (schema `description` annotation). */\n caption: string;\n /** Consumption as a whole percentage (`0`–`100`); `undefined` for an unlimited limit. */\n percent?: number;\n windowHours: number;\n};\n\n/** One display row per limit, shorter windows first. A `null` limit is reported as unlimited. */\nconst computeRows = (data: GetProfileUsageResponse, t: TFunction): UsageRow[] =>\n data.limits\n .map((limit): UsageRow => {\n const used = sumUsageForLimit(data.usage, limit);\n const label = formatLimitLabel(limit, t);\n const windowHours = limit.windowDuration / SECONDS_PER_HOUR;\n const window = formatWindow(windowHours, t);\n const key = `${limit.eventType}/${limit.subtypePattern.join(',')}/${limit.valueKey}/${limit.windowDuration}/${limit.limit ?? 'unlimited'}`;\n if (limit.limit === null) {\n return {\n key,\n label,\n caption: t('usage-unlimited.description', { used: formatAmount(used), window }),\n windowHours,\n };\n }\n const percent = limit.limit > 0 ? Math.min(100, Math.round((used / limit.limit) * 100)) : used > 0 ? 100 : 0;\n return {\n key,\n label,\n caption: `${t('usage-percent-used.label', { percent })} · ${t('usage-limit.description', { used: formatAmount(used), limit: formatAmount(limit.limit), window })}`,\n percent,\n windowHours,\n };\n })\n .sort((left, right) => left.windowHours - right.windowHours);\n\n/**\n * A single usage field: an optional number carrying its label/caption as `title`/`description`\n * annotations and the consumption percentage as its value. Optional so the form renders no required\n * markers; `Schema.Number` keeps the field context-free (`R = never`) so the struct stays assignable to `Form`.\n */\nconst usageField = (title: string, description: string) =>\n Schema.optional(Schema.Number.annotate({ title, description }));\n\n/**\n * Build the Effect schema (one annotated field per limit) and matching values. Unlimited limits have no\n * value, so their field reads `undefined` and the renderer shows the \"Unlimited\" label instead of a meter.\n */\nconst buildUsageForm = (rows: UsageRow[]) => {\n const fields: Record<string, ReturnType<typeof usageField>> = {};\n const values: Record<string, number> = {};\n rows.forEach((row, index) => {\n const field = `metric_${index}`;\n fields[field] = usageField(row.label, row.caption);\n if (row.percent !== undefined) {\n values[field] = row.percent;\n }\n });\n return { schema: Schema.Struct(fields), values };\n};\n\n/** Non-data states shown as a single `Message`, keyed by message variant (translation keys for the copy). */\nconst STATE_MESSAGES = {\n unavailable: {\n valence: 'warning',\n icon: 'ph--cloud-slash--duotone',\n title: 'usage-unavailable.title',\n description: 'usage-unavailable.description',\n },\n error: {\n valence: 'error',\n icon: 'ph--cloud-x--duotone',\n title: 'usage-offline.title',\n description: 'usage-offline.description',\n },\n empty: {\n valence: 'neutral',\n icon: 'ph--chart-bar--duotone',\n title: 'usage-empty.title',\n description: 'usage-empty.description',\n },\n} as const;\n\n/**\n * Presentational view of profile usage: renders loading/error/unavailable/empty states, or a\n * schema-driven settings form (one read-only field per limit), plus a refresh control and a\n * collapsible raw-response viewer. Pure — all data via props.\n */\nexport const UsageView = ({ state, data, lastUpdated, onRefresh }: UsageViewProps) => {\n const { t } = useTranslation(meta.profile.key);\n const [rawExpanded, setRawExpanded] = useState(false);\n\n const { schema, values, empty } = useMemo(() => {\n const rows = data ? computeRows(data, t) : [];\n return { ...buildUsageForm(rows), empty: rows.length === 0 };\n }, [data, t]);\n\n // Non-data states resolve to a `Message`; `loading` shows a spinner and `ready` with data shows the form.\n const message =\n state === 'unavailable'\n ? STATE_MESSAGES.unavailable\n : state === 'error'\n ? STATE_MESSAGES.error\n : state === 'ready' && empty\n ? STATE_MESSAGES.empty\n : undefined;\n\n // Render each metric as a meter from its percentage value; unlimited limits (no value) show a label.\n const meterFieldProvider = useCallback<FormFieldProvider>(\n ({ fieldProps: { label, description, getValue } }) => {\n const percent = getValue();\n return (\n <Form.Row label={label} description={description}>\n {typeof percent === 'number' ? (\n <Progress progress={percent / 100} aria-label={t('usage-percent-used.label', { percent })} />\n ) : (\n t('usage-unlimited.label')\n )}\n </Form.Row>\n );\n },\n [t],\n );\n\n return (\n <Form.Root variant='settings' layout='static' schema={schema} values={values}>\n <Form.Viewport scroll>\n <Form.Content>\n <Form.Section title={t('usage-section.title')} description={t('usage-section.description')}>\n {message ? (\n <Banner.Root valence={message.valence}>\n <Banner.Content>\n <Banner.Title icon={message.icon}>{t(message.title)}</Banner.Title>\n <Banner.Body>{t(message.description)}</Banner.Body>\n </Banner.Content>\n </Banner.Root>\n ) : (\n <Form.FieldSet fieldProvider={meterFieldProvider} />\n )}\n </Form.Section>\n\n {/* {state === 'ready' && data && (\n <Form.Section>\n <Form.Row\n label={\n lastUpdated !== undefined\n ? t('usage-last-updated.label', { time: new Date(lastUpdated).toLocaleTimeString() })\n : t('usage-refresh.label')\n }\n >\n {onRefresh && (\n <IconButton\n iconOnly\n variant='ghost'\n icon='ph--arrow-clockwise--regular'\n label={t('usage-refresh.label')}\n onClick={onRefresh}\n />\n )}\n </Form.Row>\n </Form.Section>\n )} */}\n\n {/* {state === 'ready' && data && (\n <Form.Section>\n <Form.Row label={t('usage-raw-json.label')}>\n <ToggleIconButton\n iconOnly\n variant='ghost'\n active={rawExpanded}\n icon='ph--caret-right--regular'\n label={t('usage-raw-json.label')}\n onClick={() => setRawExpanded((value) => !value)}\n />\n </Form.Row>\n {rawExpanded && <JsonHighlighter data={data} testId='usage-raw-json' />}\n </Form.Section>\n )} */}\n </Form.Content>\n </Form.Viewport>\n </Form.Root>\n );\n};\n\nUsageView.displayName = 'UsageView';\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport React, { useCallback, useState } from 'react';\n\nimport { Context } from '@dxos/context';\nimport { log } from '@dxos/log';\nimport { type GetProfileUsageResponse } from '@dxos/protocols';\nimport { useAsyncEffect } from '@dxos/react-ui';\n\nimport { useHubHttpClient } from '../../hooks';\nimport { UsageView, type UsageViewState } from './UsageView';\n\n/** State + payload kept together so `ready` always carries data (mirrors the discriminated `UsageViewProps`). */\ntype UsageFetchState =\n | {\n state: Exclude<UsageViewState, 'ready'>;\n }\n | {\n state: 'ready';\n data: GetProfileUsageResponse;\n };\n\n/**\n * Fetches rolling-window profile usage from the hub service and renders it.\n * Connected wrapper around the presentational {@link UsageView}.\n */\nexport const UsageContainer = () => {\n const hubHttp = useHubHttpClient();\n const [fetchState, setFetchState] = useState<UsageFetchState>({ state: 'loading' });\n const [lastUpdated, setLastUpdated] = useState<number | undefined>();\n const [refreshCount, setRefreshCount] = useState(0);\n\n useAsyncEffect(async () => {\n if (!hubHttp) {\n setFetchState({ state: 'unavailable' });\n return;\n }\n // Keep prior data visible while refetching; only show the loading state on first load.\n setFetchState((previous) => (previous.state === 'ready' ? previous : { state: 'loading' }));\n try {\n const result = await hubHttp.getProfileUsage(new Context());\n setFetchState({ state: 'ready', data: result });\n setLastUpdated(Date.now());\n } catch (err) {\n log.catch(err);\n setFetchState({ state: 'error' });\n }\n }, [hubHttp, refreshCount]);\n\n const handleRefresh = useCallback(() => setRefreshCount((count) => count + 1), []);\n\n return <UsageView {...fetchState} lastUpdated={lastUpdated} onRefresh={handleRefresh} />;\n};\n\nUsageContainer.displayName = 'UsageContainer';\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"chunk-UsageContainer.mjs","names":[],"sources":["../../src/containers/UsageContainer/UsageView.tsx","../../src/containers/UsageContainer/UsageContainer.tsx"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Schema from 'effect/Schema';\nimport React, { useCallback, useMemo, useState } from 'react';\n\nimport { type GetProfileUsageResponse, type MeteringLimit, type MeteringUsageItem } from '@dxos/protocols';\nimport { Form, type FormFieldProvider } from '@dxos/react-ui-form';\nimport * as Banner from '@dxos/react-ui/Banner';\nimport * as Hooks from '@dxos/react-ui/Hooks';\nimport * as Status from '@dxos/react-ui/Status';\n\nimport { meta } from '#meta';\n\nexport type UsageViewState = 'loading' | 'ready' | 'error' | 'unavailable';\n\ntype UsageViewCommonProps = {\n /** Epoch milliseconds of the last successful fetch. */\n lastUpdated?: number;\n /** Invoked when the user requests a refresh. */\n onRefresh?: () => void;\n};\n\n/**\n * Discriminated on `state`: the payload is required (and only present) when `state` is `'ready'`, so a\n * missing payload can't be silently rendered as an empty plan.\n */\nexport type UsageViewProps =\n | (UsageViewCommonProps & { state: Exclude<UsageViewState, 'ready'>; data?: undefined })\n | (UsageViewCommonProps & { state: 'ready'; data: GetProfileUsageResponse });\n\ntype TFunction = (key: string, options?: Record<string, unknown>) => string;\n\n/**\n * Whether a usage row falls under a limit. Subtype segments are matched positionally against\n * `subtypePattern` where `*` matches any segment.\n */\nconst usageMatchesLimit = (item: MeteringUsageItem, limit: MeteringLimit): boolean => {\n if (item.eventType !== limit.eventType || item.valueKey !== limit.valueKey) {\n return false;\n }\n return limit.subtypePattern.every((pattern, index) => pattern === '*' || pattern === item.subtypePattern[index]);\n};\n\n/** Sum every usage item that falls under the limit. */\nconst sumUsageForLimit = (usage: GetProfileUsageResponse['usage'], limit: MeteringLimit): number =>\n usage.reduce((total, item) => (usageMatchesLimit(item, limit) ? total + item.amount : total), 0);\n\n/** Humanize a camelCase value key, e.g. `outputTokens` → `output tokens`. */\nconst formatValueKey = (valueKey: string): string =>\n valueKey\n .replace(/([A-Z])/g, ' $1')\n .trim()\n .toLowerCase();\n\n/**\n * Human label for a limit: a scope followed by the value key, e.g.\n * `{ eventType: 'ai', valueKey: 'outputTokens', subtypePattern: ['*'] }` → `All models · output tokens`,\n * `{ eventType: 'ai', valueKey: 'inputTokens', subtypePattern: ['claude-opus-4'] }` → `claude-opus-4 · input tokens`.\n */\nconst formatLimitLabel = (limit: MeteringLimit, t: TFunction): string => {\n const metric = formatValueKey(limit.valueKey);\n const subtype = limit.subtypePattern.filter((segment) => segment && segment !== '*').join('/');\n if (limit.eventType === 'ai') {\n return `${subtype || t('usage-all-models.label')} · ${metric}`;\n }\n return `${subtype ? `${limit.eventType}/${subtype}` : limit.eventType} · ${metric}`;\n};\n\nconst SECONDS_PER_HOUR = 60 * 60;\n\n/** Render `windowHours` as a localized \"N months / days / hours\" string. */\nconst formatWindow = (windowHours: number, t: TFunction): string => {\n if (windowHours % (24 * 30) === 0) {\n return t('usage-window-months.label', { count: windowHours / (24 * 30) });\n }\n if (windowHours % 24 === 0) {\n return t('usage-window-days.label', { count: windowHours / 24 });\n }\n return t('usage-window-hours.label', { count: windowHours });\n};\n\ntype UsageRow = {\n key: string;\n /** Field label (schema `title` annotation). */\n label: string;\n /** Field caption (schema `description` annotation). */\n caption: string;\n /** Consumption as a whole percentage (`0`–`100`); `undefined` for an unlimited limit. */\n percent?: number;\n windowHours: number;\n};\n\n/** One display row per limit, shorter windows first. A `null` limit is reported as unlimited. */\nconst computeRows = (data: GetProfileUsageResponse, t: TFunction): UsageRow[] =>\n data.limits\n .map((limit): UsageRow => {\n const used = sumUsageForLimit(data.usage, limit);\n const label = formatLimitLabel(limit, t);\n const windowHours = limit.windowDuration / SECONDS_PER_HOUR;\n const window = formatWindow(windowHours, t);\n const key = `${limit.eventType}/${limit.subtypePattern.join(',')}/${limit.valueKey}/${limit.windowDuration}/${limit.limit ?? 'unlimited'}`;\n if (limit.limit === null) {\n return {\n key,\n label,\n caption: t('usage-unlimited.description', { used: used.toLocaleString(), window }),\n windowHours,\n };\n }\n const percent = limit.limit > 0 ? Math.min(100, Math.round((used / limit.limit) * 100)) : used > 0 ? 100 : 0;\n return {\n key,\n label,\n caption: `${t('usage-percent-used.label', { percent })} · ${t('usage-limit.description', { used: used.toLocaleString(), limit: limit.limit.toLocaleString(), window })}`,\n percent,\n windowHours,\n };\n })\n .sort((left, right) => left.windowHours - right.windowHours);\n\n/**\n * A single usage field: an optional number carrying its label/caption as `title`/`description`\n * annotations and the consumption percentage as its value. Optional so the form renders no required\n * markers; `Schema.Number` keeps the field context-free (`R = never`) so the struct stays assignable to `Form`.\n */\nconst usageField = (title: string, description: string) =>\n Schema.optional(Schema.Number.annotate({ title, description }));\n\n/**\n * Build the Effect schema (one annotated field per limit) and matching values. Unlimited limits have no\n * value, so their field reads `undefined` and the renderer shows the \"Unlimited\" label instead of a meter.\n */\nconst buildUsageForm = (rows: UsageRow[]) => {\n const fields: Record<string, ReturnType<typeof usageField>> = {};\n const values: Record<string, number> = {};\n rows.forEach((row, index) => {\n const field = `metric_${index}`;\n fields[field] = usageField(row.label, row.caption);\n if (row.percent !== undefined) {\n values[field] = row.percent;\n }\n });\n return { schema: Schema.Struct(fields), values };\n};\n\n/** Non-data states shown as a single `Message`, keyed by message variant (translation keys for the copy). */\nconst STATE_MESSAGES = {\n unavailable: {\n valence: 'warning',\n icon: 'ph--cloud-slash--duotone',\n title: 'usage-unavailable.title',\n description: 'usage-unavailable.description',\n },\n error: {\n valence: 'error',\n icon: 'ph--cloud-x--duotone',\n title: 'usage-offline.title',\n description: 'usage-offline.description',\n },\n empty: {\n valence: 'neutral',\n icon: 'ph--chart-bar--duotone',\n title: 'usage-empty.title',\n description: 'usage-empty.description',\n },\n} as const;\n\n/**\n * Presentational view of profile usage: renders loading/error/unavailable/empty states, or a\n * schema-driven settings form (one read-only field per limit), plus a refresh control and a\n * collapsible raw-response viewer. Pure — all data via props.\n */\nexport const UsageView = ({ state, data, lastUpdated, onRefresh }: UsageViewProps) => {\n const { t } = Hooks.useTranslation(meta.profile.key);\n const [rawExpanded, setRawExpanded] = useState(false);\n\n const { schema, values, empty } = useMemo(() => {\n const rows = data ? computeRows(data, t) : [];\n return { ...buildUsageForm(rows), empty: rows.length === 0 };\n }, [data, t]);\n\n // Non-data states resolve to a `Message`; `loading` shows a spinner and `ready` with data shows the form.\n const message =\n state === 'unavailable'\n ? STATE_MESSAGES.unavailable\n : state === 'error'\n ? STATE_MESSAGES.error\n : state === 'ready' && empty\n ? STATE_MESSAGES.empty\n : undefined;\n\n // Render each metric as a meter from its percentage value; unlimited limits (no value) show a label.\n const meterFieldProvider = useCallback<FormFieldProvider>(\n ({ fieldProps: { label, description, getValue } }) => {\n const percent = getValue();\n return (\n <Form.Field standalone label={label} description={description}>\n {typeof percent === 'number' ? (\n <Status.Progress value={percent / 100} label={t('usage-percent-used.label', { percent })} />\n ) : (\n t('usage-unlimited.label')\n )}\n </Form.Field>\n );\n },\n [t],\n );\n\n return (\n <Form.Root variant='settings' layout='static' schema={schema} values={values}>\n <Form.Viewport scroll>\n <Form.Content>\n <Form.FieldSet label={t('usage-section.title')} description={t('usage-section.description')}>\n {message ? (\n <Banner.Root valence={message.valence}>\n <Banner.Title icon={message.icon}>{t(message.title)}</Banner.Title>\n <Banner.Body>{t(message.description)}</Banner.Body>\n </Banner.Root>\n ) : (\n <Form.Fields fieldProvider={meterFieldProvider} />\n )}\n </Form.FieldSet>\n\n {/* {state === 'ready' && data && (\n <Form.FieldSet>\n <Form.Field standalone\n label={\n lastUpdated !== undefined\n ? t('usage-last-updated.label', { time: new Date(lastUpdated).toLocaleTimeString() })\n : t('usage-refresh.label')\n }\n >\n {onRefresh && (\n <IconButton\n iconOnly\n variant='ghost'\n icon='ph--arrow-clockwise--regular'\n label={t('usage-refresh.label')}\n onClick={onRefresh}\n />\n )}\n </Form.Field>\n </Form.FieldSet>\n )} */}\n\n {/* {state === 'ready' && data && (\n <Form.FieldSet>\n <Form.Field standalone label={t('usage-raw-json.label')}>\n <ToggleIconButton\n iconOnly\n variant='ghost'\n active={rawExpanded}\n icon='ph--caret-right--regular'\n label={t('usage-raw-json.label')}\n onClick={() => setRawExpanded((value) => !value)}\n />\n </Form.Field>\n {rawExpanded && <JsonHighlighter data={data} testId='usage-raw-json' />}\n </Form.FieldSet>\n )} */}\n </Form.Content>\n </Form.Viewport>\n </Form.Root>\n );\n};\n\nUsageView.displayName = 'UsageView';\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport React, { useCallback, useState } from 'react';\n\nimport { Context } from '@dxos/context';\nimport { log } from '@dxos/log';\nimport { type GetProfileUsageResponse } from '@dxos/protocols';\nimport * as Hooks from '@dxos/react-ui/Hooks';\n\nimport { useHubHttpClient } from '../../hooks/index.ts';\nimport { UsageView, type UsageViewState } from './UsageView.tsx';\n\n/** State + payload kept together so `ready` always carries data (mirrors the discriminated `UsageViewProps`). */\ntype UsageFetchState =\n | {\n state: Exclude<UsageViewState, 'ready'>;\n }\n | {\n state: 'ready';\n data: GetProfileUsageResponse;\n };\n\n/**\n * Fetches rolling-window profile usage from the hub service and renders it.\n * Connected wrapper around the presentational {@link UsageView}.\n */\nexport const UsageContainer = () => {\n const hubHttp = useHubHttpClient();\n const [fetchState, setFetchState] = useState<UsageFetchState>({ state: 'loading' });\n const [lastUpdated, setLastUpdated] = useState<number | undefined>();\n const [refreshCount, setRefreshCount] = useState(0);\n\n Hooks.useAsyncEffect(async () => {\n if (!hubHttp) {\n setFetchState({ state: 'unavailable' });\n return;\n }\n // Keep prior data visible while refetching; only show the loading state on first load.\n setFetchState((previous) => (previous.state === 'ready' ? previous : { state: 'loading' }));\n try {\n const result = await hubHttp.getProfileUsage(new Context());\n setFetchState({ state: 'ready', data: result });\n setLastUpdated(Date.now());\n } catch (err) {\n log.catch(err);\n setFetchState({ state: 'error' });\n }\n }, [hubHttp, refreshCount]);\n\n const handleRefresh = useCallback(() => setRefreshCount((count) => count + 1), []);\n\n return <UsageView {...fetchState} lastUpdated={lastUpdated} onRefresh={handleRefresh} />;\n};\n\nUsageContainer.displayName = 'UsageContainer';\n"],"mappings":"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"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as Capability from "@dxos/app-framework/Capability";
|
|
2
2
|
import { AccountCache, ClientCapabilities } from "#types";
|
|
3
3
|
import * as Effect from "effect/Effect";
|
|
4
|
-
import
|
|
4
|
+
import * as KvsStore from "@dxos/effect/KvsStore";
|
|
5
5
|
//#region src/capabilities/account-cache.ts
|
|
6
|
-
var account_cache_default = Capability.makeModule(() => Effect.succeed(Capability.contribute(ClientCapabilities.AccountCache,
|
|
6
|
+
var account_cache_default = Capability.makeModule(() => Effect.succeed(Capability.contribute(ClientCapabilities.AccountCache, KvsStore.make({
|
|
7
7
|
key: "composer.account",
|
|
8
8
|
schema: AccountCache.AccountCache,
|
|
9
9
|
defaultValue: () => ({})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chunk-account-cache.mjs","names":[],"sources":["../../src/capabilities/account-cache.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport * as Capability from '@dxos/app-framework/Capability';\nimport
|
|
1
|
+
{"version":3,"file":"chunk-account-cache.mjs","names":[],"sources":["../../src/capabilities/account-cache.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport * as Capability from '@dxos/app-framework/Capability';\nimport * as KvsStore from '@dxos/effect/KvsStore';\n\nimport { AccountCache, ClientCapabilities } from '#types';\n\nexport default Capability.makeModule(() =>\n Effect.succeed(\n Capability.contribute(\n ClientCapabilities.AccountCache,\n KvsStore.make<AccountCache.AccountCache>({\n key: 'composer.account',\n schema: AccountCache.AccountCache,\n defaultValue: () => ({}),\n }),\n ),\n ),\n);\n"],"mappings":";;;;;AAWA,IAAA,wBAAe,WAAW,iBACxB,OAAO,QACL,WAAW,WACT,mBAAmB,cACnB,SAAS,KAAgC;CACvC,KAAK;CACL,QAAQ,aAAa;CACrB,qBAAqB,CAAC;AACxB,CAAC,CACH,CACF,CACF"}
|
|
@@ -4,8 +4,8 @@ import { Account, ClientCapabilities } from "#types";
|
|
|
4
4
|
import * as Effect from "effect/Effect";
|
|
5
5
|
import * as Option from "effect/Option";
|
|
6
6
|
import { ClientOperation } from "#operations";
|
|
7
|
-
import { meta } from "#meta";
|
|
8
7
|
import { Identity } from "@dxos/halo";
|
|
8
|
+
import { meta } from "#meta";
|
|
9
9
|
import * as Operation from "@dxos/compute/Operation";
|
|
10
10
|
import * as AppGraphBuilder from "@dxos/app-graph/AppGraphBuilder";
|
|
11
11
|
import * as AppGraphNode from "@dxos/app-graph/AppGraphNode";
|
|
@@ -15,6 +15,7 @@ import * as GraphNodeMatcher from "@dxos/graph/GraphNodeMatcher";
|
|
|
15
15
|
//#region src/capabilities/app-graph-builder.ts
|
|
16
16
|
var app_graph_builder_default = Capability.makeModule(Effect.fnUntraced(function* () {
|
|
17
17
|
const clientAtom = yield* Capability.atom(ClientCapabilities.Client);
|
|
18
|
+
const hasHub = (clients) => !!clients[0]?.config.values?.runtime?.app?.env?.DX_HUB_URL;
|
|
18
19
|
const identityServiceAtom = yield* Capability.atom(ClientCapabilities.IdentityService);
|
|
19
20
|
const extensions = yield* AppGraphBuilder.createExtension({
|
|
20
21
|
id: "root",
|
|
@@ -39,7 +40,7 @@ var app_graph_builder_default = Capability.makeModule(Effect.fnUntraced(function
|
|
|
39
40
|
const [identityService] = get(identityServiceAtom);
|
|
40
41
|
const identity = identityService ? Option.getOrUndefined(get(Identity.atom(identityService))) : void 0;
|
|
41
42
|
const status = get(CreateAtom.fromObservable(client.mesh.networkStatus));
|
|
42
|
-
|
|
43
|
+
hasHub([client]);
|
|
43
44
|
return [AppGraphNode.make({
|
|
44
45
|
id: Account.id,
|
|
45
46
|
type: meta.profile.key,
|
|
@@ -52,67 +53,165 @@ var app_graph_builder_default = Capability.makeModule(Effect.fnUntraced(function
|
|
|
52
53
|
hue: identity?.data?.hue,
|
|
53
54
|
emoji: identity?.data?.emoji,
|
|
54
55
|
status: status.swarm === ConnectionState.OFFLINE ? "error" : "active"
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
56
|
+
}
|
|
57
|
+
})];
|
|
58
|
+
}).pipe(Effect.orDie)
|
|
59
|
+
});
|
|
60
|
+
const accountProfile = yield* AppGraphBuilder.createExtension({
|
|
61
|
+
id: "accountProfile",
|
|
62
|
+
url: {
|
|
63
|
+
key: Account.Profile,
|
|
64
|
+
kind: "singleton",
|
|
65
|
+
path: []
|
|
66
|
+
},
|
|
67
|
+
match: GraphNodeMatcher.whenId(Account.workspacePath),
|
|
68
|
+
connector: (_node, get) => Effect.gen(function* () {
|
|
69
|
+
return [AppGraphNode.make({
|
|
70
|
+
id: Account.Profile,
|
|
71
|
+
data: Account.path(Account.Profile),
|
|
72
|
+
type: meta.profile.key,
|
|
73
|
+
properties: {
|
|
74
|
+
label: ["profile.label", { ns: meta.profile.key }],
|
|
75
|
+
icon: "ph--user--regular",
|
|
76
|
+
testId: "clientPlugin.profile"
|
|
77
|
+
}
|
|
78
|
+
})];
|
|
79
|
+
}).pipe(Effect.orDie)
|
|
80
|
+
});
|
|
81
|
+
const accountAccount = yield* AppGraphBuilder.createExtension({
|
|
82
|
+
id: "accountAccount",
|
|
83
|
+
url: {
|
|
84
|
+
key: Account.Account,
|
|
85
|
+
kind: "singleton",
|
|
86
|
+
path: []
|
|
87
|
+
},
|
|
88
|
+
match: GraphNodeMatcher.whenId(Account.workspacePath),
|
|
89
|
+
connector: (_node, get) => Effect.gen(function* () {
|
|
90
|
+
if (!hasHub(get(clientAtom))) return [];
|
|
91
|
+
return [AppGraphNode.make({
|
|
92
|
+
id: Account.Account,
|
|
93
|
+
data: Account.path(Account.Account),
|
|
94
|
+
type: meta.profile.key,
|
|
95
|
+
properties: {
|
|
96
|
+
label: ["account-panel.label", { ns: meta.profile.key }],
|
|
97
|
+
icon: "ph--identification-card--regular"
|
|
98
|
+
}
|
|
99
|
+
})];
|
|
100
|
+
}).pipe(Effect.orDie)
|
|
101
|
+
});
|
|
102
|
+
const accountSecurity = yield* AppGraphBuilder.createExtension({
|
|
103
|
+
id: "accountSecurity",
|
|
104
|
+
url: {
|
|
105
|
+
key: Account.Security,
|
|
106
|
+
kind: "singleton",
|
|
107
|
+
path: []
|
|
108
|
+
},
|
|
109
|
+
match: GraphNodeMatcher.whenId(Account.workspacePath),
|
|
110
|
+
connector: (_node, get) => Effect.gen(function* () {
|
|
111
|
+
return [AppGraphNode.make({
|
|
112
|
+
id: Account.Security,
|
|
113
|
+
data: Account.path(Account.Security),
|
|
114
|
+
type: meta.profile.key,
|
|
115
|
+
properties: {
|
|
116
|
+
label: ["security.label", { ns: meta.profile.key }],
|
|
117
|
+
icon: "ph--key--regular",
|
|
118
|
+
testId: "clientPlugin.security"
|
|
119
|
+
}
|
|
120
|
+
})];
|
|
121
|
+
}).pipe(Effect.orDie)
|
|
122
|
+
});
|
|
123
|
+
const accountDevices = yield* AppGraphBuilder.createExtension({
|
|
124
|
+
id: "accountDevices",
|
|
125
|
+
url: {
|
|
126
|
+
key: Account.Devices,
|
|
127
|
+
kind: "singleton",
|
|
128
|
+
path: []
|
|
129
|
+
},
|
|
130
|
+
match: GraphNodeMatcher.whenId(Account.workspacePath),
|
|
131
|
+
connector: (_node, get) => Effect.gen(function* () {
|
|
132
|
+
return [AppGraphNode.make({
|
|
133
|
+
id: Account.Devices,
|
|
134
|
+
data: Account.path(Account.Devices),
|
|
135
|
+
type: meta.profile.key,
|
|
136
|
+
properties: {
|
|
137
|
+
label: ["devices.label", { ns: meta.profile.key }],
|
|
138
|
+
icon: "ph--devices--regular",
|
|
139
|
+
testId: "clientPlugin.devices"
|
|
140
|
+
}
|
|
141
|
+
})];
|
|
142
|
+
}).pipe(Effect.orDie)
|
|
143
|
+
});
|
|
144
|
+
const accountContacts = yield* AppGraphBuilder.createExtension({
|
|
145
|
+
id: "accountContacts",
|
|
146
|
+
url: {
|
|
147
|
+
key: Account.Contacts,
|
|
148
|
+
kind: "singleton",
|
|
149
|
+
path: []
|
|
150
|
+
},
|
|
151
|
+
match: GraphNodeMatcher.whenId(Account.workspacePath),
|
|
152
|
+
connector: () => Effect.succeed([AppGraphNode.make({
|
|
153
|
+
id: Account.Contacts,
|
|
154
|
+
data: Account.path(Account.Contacts),
|
|
155
|
+
type: meta.profile.key,
|
|
156
|
+
properties: {
|
|
157
|
+
label: ["contacts.label", { ns: meta.profile.key }],
|
|
158
|
+
icon: "ph--address-book--regular",
|
|
159
|
+
testId: "clientPlugin.contacts"
|
|
160
|
+
}
|
|
161
|
+
})])
|
|
162
|
+
});
|
|
163
|
+
const accountInvitations = yield* AppGraphBuilder.createExtension({
|
|
164
|
+
id: "accountInvitations",
|
|
165
|
+
url: {
|
|
166
|
+
key: Account.Invitations,
|
|
167
|
+
kind: "singleton",
|
|
168
|
+
path: []
|
|
169
|
+
},
|
|
170
|
+
match: GraphNodeMatcher.whenId(Account.workspacePath),
|
|
171
|
+
connector: (_node, get) => Effect.gen(function* () {
|
|
172
|
+
if (!hasHub(get(clientAtom))) return [];
|
|
173
|
+
return [AppGraphNode.make({
|
|
174
|
+
id: Account.Invitations,
|
|
175
|
+
data: Account.path(Account.Invitations),
|
|
176
|
+
type: meta.profile.key,
|
|
177
|
+
properties: {
|
|
178
|
+
label: ["invitations-panel.label", { ns: meta.profile.key }],
|
|
179
|
+
icon: "ph--ticket--regular"
|
|
180
|
+
}
|
|
181
|
+
})];
|
|
182
|
+
}).pipe(Effect.orDie)
|
|
183
|
+
});
|
|
184
|
+
const accountUsage = yield* AppGraphBuilder.createExtension({
|
|
185
|
+
id: "accountUsage",
|
|
186
|
+
url: {
|
|
187
|
+
key: Account.Usage,
|
|
188
|
+
kind: "singleton",
|
|
189
|
+
path: []
|
|
190
|
+
},
|
|
191
|
+
match: GraphNodeMatcher.whenId(Account.workspacePath),
|
|
192
|
+
connector: (_node, get) => Effect.gen(function* () {
|
|
193
|
+
if (!hasHub(get(clientAtom))) return [];
|
|
194
|
+
return [AppGraphNode.make({
|
|
195
|
+
id: Account.Usage,
|
|
196
|
+
data: Account.path(Account.Usage),
|
|
197
|
+
type: meta.profile.key,
|
|
198
|
+
properties: {
|
|
199
|
+
label: ["usage-panel.label", { ns: meta.profile.key }],
|
|
200
|
+
icon: "ph--chart-bar--regular"
|
|
201
|
+
}
|
|
112
202
|
})];
|
|
113
203
|
}).pipe(Effect.orDie)
|
|
114
204
|
});
|
|
115
|
-
return Capability.contribute(AppCapabilities.AppGraphBuilder,
|
|
205
|
+
return Capability.contribute(AppCapabilities.AppGraphBuilder, [
|
|
206
|
+
...extensions,
|
|
207
|
+
...accountProfile,
|
|
208
|
+
...accountAccount,
|
|
209
|
+
...accountSecurity,
|
|
210
|
+
...accountDevices,
|
|
211
|
+
...accountContacts,
|
|
212
|
+
...accountInvitations,
|
|
213
|
+
...accountUsage
|
|
214
|
+
]);
|
|
116
215
|
}));
|
|
117
216
|
//#endregion
|
|
118
217
|
export { app_graph_builder_default as default };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chunk-app-graph-builder.mjs","names":[],"sources":["../../src/capabilities/app-graph-builder.ts"],"sourcesContent":["//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\nimport * as Option from 'effect/Option';\n\nimport * as Capability from '@dxos/app-framework/Capability';\nimport * as AppGraphBuilder from '@dxos/app-graph/AppGraphBuilder';\nimport * as AppGraphNode from '@dxos/app-graph/AppGraphNode';\nimport * as CreateAtom from '@dxos/app-graph/CreateAtom';\nimport * as AppCapabilities from '@dxos/app-toolkit/AppCapabilities';\nimport { ConnectionState } from '@dxos/client/mesh';\nimport * as Operation from '@dxos/compute/Operation';\nimport * as GraphNodeMatcher from '@dxos/graph/GraphNodeMatcher';\nimport { Identity } from '@dxos/halo';\n\nimport { meta } from '#meta';\nimport { ClientOperation } from '#operations';\nimport { Account, ClientCapabilities } from '#types';\n\nexport default Capability.makeModule(\n Effect.fnUntraced(function* () {\n // Read the client through its atom so the extension establishes a reactive dependency:\n // the connector may evaluate before the client module finishes activating (dependency\n // modules contribute individually, not batched per wave) and re-evaluates when it lands.\n const clientAtom = yield* Capability.atom(ClientCapabilities.Client);\n const identityServiceAtom = yield* Capability.atom(ClientCapabilities.IdentityService);\n const extensions = yield* AppGraphBuilder.createExtension({\n id: 'root',\n match: GraphNodeMatcher.whenRoot,\n actions: () =>\n Effect.succeed([\n {\n id: 'openUserAccount',\n data: () => Operation.invoke(ClientOperation.ShareIdentity),\n properties: {\n label: ['open-user-account.label', { ns: meta.profile.key }],\n icon: 'ph--user--regular',\n disposition: 'menu',\n keyBinding: {\n macos: 'meta+shift+.',\n // TODO(wittjosiah): Test on windows to see if it behaves the same as linux.\n windows: 'alt+shift+.',\n linux: 'alt+shift+>',\n },\n },\n },\n ]),\n connector: (node, get) =>\n Effect.gen(function* () {\n const [client] = get(clientAtom);\n if (!client) {\n return [];\n }\n const [identityService] = get(identityServiceAtom);\n const identity = identityService ? Option.getOrUndefined(get(Identity.atom(identityService))) : undefined;\n const status = get(CreateAtom.fromObservable(client.mesh.networkStatus));\n // Account, invitations, and usage are all hub-service reads; without a hub URL there is\n // no `HubHttpClient` capability and those panels render empty shells forever.\n const hub = !!client.config.values?.runtime?.app?.env?.DX_HUB_URL;\n\n return [\n AppGraphNode.make({\n id: Account.id,\n type: meta.profile.key,\n properties: {\n label: ['account.label', { ns: meta.profile.key }],\n icon: 'ph--user--regular',\n disposition: 'user-account',\n testId: 'clientPlugin.account',\n // NOTE: This currently needs to be the identity key because the fallback is generated from hex.\n userId: identity?.identityKey,\n hue: identity?.data?.hue,\n emoji: identity?.data?.emoji,\n status: status.swarm === ConnectionState.OFFLINE ? 'error' : 'active',\n },\n nodes: [\n AppGraphNode.make({\n id: Account.Profile,\n data: Account.Profile,\n type: meta.profile.key,\n properties: {\n label: ['profile.label', { ns: meta.profile.key }],\n icon: 'ph--user--regular',\n },\n }),\n ...(hub\n ? [\n AppGraphNode.make({\n id: Account.Account,\n data: Account.Account,\n type: meta.profile.key,\n properties: {\n label: ['account-panel.label', { ns: meta.profile.key }],\n icon: 'ph--identification-card--regular',\n },\n }),\n ]\n : []),\n AppGraphNode.make({\n id: Account.Security,\n data: Account.Security,\n type: meta.profile.key,\n properties: {\n label: ['security.label', { ns: meta.profile.key }],\n icon: 'ph--key--regular',\n },\n }),\n AppGraphNode.make({\n id: Account.Devices,\n data: Account.Devices,\n type: meta.profile.key,\n properties: {\n label: ['devices.label', { ns: meta.profile.key }],\n icon: 'ph--devices--regular',\n testId: 'clientPlugin.devices',\n },\n }),\n ...(hub\n ? [\n AppGraphNode.make({\n id: Account.Invitations,\n data: Account.Invitations,\n type: meta.profile.key,\n properties: {\n label: ['invitations-panel.label', { ns: meta.profile.key }],\n icon: 'ph--ticket--regular',\n },\n }),\n AppGraphNode.make({\n id: Account.Usage,\n data: Account.Usage,\n type: meta.profile.key,\n properties: {\n label: ['usage-panel.label', { ns: meta.profile.key }],\n icon: 'ph--chart-bar--regular',\n },\n }),\n ]\n : []),\n ],\n }),\n ];\n }).pipe(Effect.orDie),\n });\n\n return Capability.contribute(AppCapabilities.AppGraphBuilder, extensions);\n }),\n);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"chunk-app-graph-builder.mjs","names":[],"sources":["../../src/capabilities/app-graph-builder.ts"],"sourcesContent":["//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\nimport * as Option from 'effect/Option';\n\nimport * as Capability from '@dxos/app-framework/Capability';\nimport * as AppGraphBuilder from '@dxos/app-graph/AppGraphBuilder';\nimport * as AppGraphNode from '@dxos/app-graph/AppGraphNode';\nimport * as CreateAtom from '@dxos/app-graph/CreateAtom';\nimport * as AppCapabilities from '@dxos/app-toolkit/AppCapabilities';\nimport { type Client } from '@dxos/client';\nimport { ConnectionState } from '@dxos/client/mesh';\nimport * as Operation from '@dxos/compute/Operation';\nimport * as GraphNodeMatcher from '@dxos/graph/GraphNodeMatcher';\nimport { Identity } from '@dxos/halo';\n\nimport { meta } from '#meta';\nimport { ClientOperation } from '#operations';\nimport { Account, ClientCapabilities } from '#types';\n\nexport default Capability.makeModule(\n Effect.fnUntraced(function* () {\n // Read the client through its atom so the extension establishes a reactive dependency:\n // the connector may evaluate before the client module finishes activating (dependency\n // modules contribute individually, not batched per wave) and re-evaluates when it lands.\n const clientAtom = yield* Capability.atom(ClientCapabilities.Client);\n // Panels backed by hub services render an empty shell without one, so they contribute no node.\n const hasHub = (clients: readonly Client[]): boolean => !!clients[0]?.config.values?.runtime?.app?.env?.DX_HUB_URL;\n const identityServiceAtom = yield* Capability.atom(ClientCapabilities.IdentityService);\n const extensions = yield* AppGraphBuilder.createExtension({\n id: 'root',\n match: GraphNodeMatcher.whenRoot,\n actions: () =>\n Effect.succeed([\n {\n id: 'openUserAccount',\n data: () => Operation.invoke(ClientOperation.ShareIdentity),\n properties: {\n label: ['open-user-account.label', { ns: meta.profile.key }],\n icon: 'ph--user--regular',\n disposition: 'menu',\n keyBinding: {\n macos: 'meta+shift+.',\n // TODO(wittjosiah): Test on windows to see if it behaves the same as linux.\n windows: 'alt+shift+.',\n linux: 'alt+shift+>',\n },\n },\n },\n ]),\n connector: (node, get) =>\n Effect.gen(function* () {\n const [client] = get(clientAtom);\n if (!client) {\n return [];\n }\n const [identityService] = get(identityServiceAtom);\n const identity = identityService ? Option.getOrUndefined(get(Identity.atom(identityService))) : undefined;\n const status = get(CreateAtom.fromObservable(client.mesh.networkStatus));\n const hub = hasHub([client]);\n\n return [\n AppGraphNode.make({\n id: Account.id,\n type: meta.profile.key,\n properties: {\n label: ['account.label', { ns: meta.profile.key }],\n icon: 'ph--user--regular',\n disposition: 'user-account',\n testId: 'clientPlugin.account',\n // NOTE: This currently needs to be the identity key because the fallback is generated from hex.\n userId: identity?.identityKey,\n hue: identity?.data?.hue,\n emoji: identity?.data?.emoji,\n status: status.swarm === ConnectionState.OFFLINE ? 'error' : 'active',\n },\n }),\n ];\n }).pipe(Effect.orDie),\n });\n\n const accountProfile = yield* AppGraphBuilder.createExtension({\n id: 'accountProfile',\n url: { key: Account.Profile, kind: 'singleton', path: [] },\n match: GraphNodeMatcher.whenId(Account.workspacePath),\n connector: (_node, get) =>\n Effect.gen(function* () {\n return [\n AppGraphNode.make({\n id: Account.Profile,\n data: Account.path(Account.Profile),\n type: meta.profile.key,\n properties: {\n label: ['profile.label', { ns: meta.profile.key }],\n icon: 'ph--user--regular',\n testId: 'clientPlugin.profile',\n },\n }),\n ];\n }).pipe(Effect.orDie),\n });\n\n const accountAccount = yield* AppGraphBuilder.createExtension({\n id: 'accountAccount',\n url: { key: Account.Account, kind: 'singleton', path: [] },\n match: GraphNodeMatcher.whenId(Account.workspacePath),\n connector: (_node, get) =>\n Effect.gen(function* () {\n if (!hasHub(get(clientAtom))) {\n return [];\n }\n return [\n AppGraphNode.make({\n id: Account.Account,\n data: Account.path(Account.Account),\n type: meta.profile.key,\n properties: {\n label: ['account-panel.label', { ns: meta.profile.key }],\n icon: 'ph--identification-card--regular',\n },\n }),\n ];\n }).pipe(Effect.orDie),\n });\n\n const accountSecurity = yield* AppGraphBuilder.createExtension({\n id: 'accountSecurity',\n url: { key: Account.Security, kind: 'singleton', path: [] },\n match: GraphNodeMatcher.whenId(Account.workspacePath),\n connector: (_node, get) =>\n Effect.gen(function* () {\n return [\n AppGraphNode.make({\n id: Account.Security,\n data: Account.path(Account.Security),\n type: meta.profile.key,\n properties: {\n label: ['security.label', { ns: meta.profile.key }],\n icon: 'ph--key--regular',\n testId: 'clientPlugin.security',\n },\n }),\n ];\n }).pipe(Effect.orDie),\n });\n\n const accountDevices = yield* AppGraphBuilder.createExtension({\n id: 'accountDevices',\n url: { key: Account.Devices, kind: 'singleton', path: [] },\n match: GraphNodeMatcher.whenId(Account.workspacePath),\n connector: (_node, get) =>\n Effect.gen(function* () {\n return [\n AppGraphNode.make({\n id: Account.Devices,\n data: Account.path(Account.Devices),\n type: meta.profile.key,\n properties: {\n label: ['devices.label', { ns: meta.profile.key }],\n icon: 'ph--devices--regular',\n testId: 'clientPlugin.devices',\n },\n }),\n ];\n }).pipe(Effect.orDie),\n });\n\n const accountContacts = yield* AppGraphBuilder.createExtension({\n id: 'accountContacts',\n url: { key: Account.Contacts, kind: 'singleton', path: [] },\n match: GraphNodeMatcher.whenId(Account.workspacePath),\n connector: () =>\n Effect.succeed([\n AppGraphNode.make({\n id: Account.Contacts,\n data: Account.path(Account.Contacts),\n type: meta.profile.key,\n properties: {\n label: ['contacts.label', { ns: meta.profile.key }],\n icon: 'ph--address-book--regular',\n testId: 'clientPlugin.contacts',\n },\n }),\n ]),\n });\n\n const accountInvitations = yield* AppGraphBuilder.createExtension({\n id: 'accountInvitations',\n url: { key: Account.Invitations, kind: 'singleton', path: [] },\n match: GraphNodeMatcher.whenId(Account.workspacePath),\n connector: (_node, get) =>\n Effect.gen(function* () {\n if (!hasHub(get(clientAtom))) {\n return [];\n }\n return [\n AppGraphNode.make({\n id: Account.Invitations,\n data: Account.path(Account.Invitations),\n type: meta.profile.key,\n properties: {\n label: ['invitations-panel.label', { ns: meta.profile.key }],\n icon: 'ph--ticket--regular',\n },\n }),\n ];\n }).pipe(Effect.orDie),\n });\n\n const accountUsage = yield* AppGraphBuilder.createExtension({\n id: 'accountUsage',\n url: { key: Account.Usage, kind: 'singleton', path: [] },\n match: GraphNodeMatcher.whenId(Account.workspacePath),\n connector: (_node, get) =>\n Effect.gen(function* () {\n if (!hasHub(get(clientAtom))) {\n return [];\n }\n return [\n AppGraphNode.make({\n id: Account.Usage,\n data: Account.path(Account.Usage),\n type: meta.profile.key,\n properties: {\n label: ['usage-panel.label', { ns: meta.profile.key }],\n icon: 'ph--chart-bar--regular',\n },\n }),\n ];\n }).pipe(Effect.orDie),\n });\n\n return Capability.contribute(AppCapabilities.AppGraphBuilder, [\n ...extensions,\n ...accountProfile,\n ...accountAccount,\n ...accountSecurity,\n ...accountDevices,\n ...accountContacts,\n ...accountInvitations,\n ...accountUsage,\n ]);\n }),\n);\n"],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as Capability from "@dxos/app-framework/Capability";
|
|
2
|
+
import { ClientCapabilities } from "#types";
|
|
3
|
+
import * as Effect from "effect/Effect";
|
|
4
|
+
//#region src/capabilities/client-services.ts
|
|
5
|
+
/**
|
|
6
|
+
* Exposes the pieces of the client that plugins read directly — config, the EDGE HTTP client and
|
|
7
|
+
* the ECHO graph — as capabilities, so those plugins need not depend on `@dxos/client`.
|
|
8
|
+
*/
|
|
9
|
+
var client_services_default = Capability.makeModule(Effect.fnUntraced(function* () {
|
|
10
|
+
const client = yield* ClientCapabilities.Client;
|
|
11
|
+
const edgeUrl = client.config.get("runtime.services.edge.url");
|
|
12
|
+
return [
|
|
13
|
+
Capability.contribute(ClientCapabilities.Config, client.config),
|
|
14
|
+
Capability.contribute(ClientCapabilities.Hypergraph, client.graph),
|
|
15
|
+
...edgeUrl ? [Capability.contribute(ClientCapabilities.EdgeHttpClient, client.edge.http)] : []
|
|
16
|
+
];
|
|
17
|
+
}));
|
|
18
|
+
//#endregion
|
|
19
|
+
export { client_services_default as default };
|
|
20
|
+
|
|
21
|
+
//# sourceMappingURL=chunk-client-services.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunk-client-services.mjs","names":[],"sources":["../../src/capabilities/client-services.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport * as Capability from '@dxos/app-framework/Capability';\n\nimport { ClientCapabilities } from '#types';\n\n/**\n * Exposes the pieces of the client that plugins read directly — config, the EDGE HTTP client and\n * the ECHO graph — as capabilities, so those plugins need not depend on `@dxos/client`.\n */\nexport default Capability.makeModule(\n Effect.fnUntraced(function* () {\n const client = yield* ClientCapabilities.Client;\n const edgeUrl = client.config.get('runtime.services.edge.url');\n return [\n Capability.contribute(ClientCapabilities.Config, client.config),\n Capability.contribute(ClientCapabilities.Hypergraph, client.graph),\n ...(edgeUrl ? [Capability.contribute(ClientCapabilities.EdgeHttpClient, client.edge.http)] : []),\n ];\n }),\n);\n"],"mappings":";;;;;;;;AAcA,IAAA,0BAAe,WAAW,WACxB,OAAO,WAAW,aAAa;CAC7B,MAAM,SAAS,OAAO,mBAAmB;CACzC,MAAM,UAAU,OAAO,OAAO,IAAI,2BAA2B;CAC7D,OAAO;EACL,WAAW,WAAW,mBAAmB,QAAQ,OAAO,MAAM;EAC9D,WAAW,WAAW,mBAAmB,YAAY,OAAO,KAAK;EACjE,GAAI,UAAU,CAAC,WAAW,WAAW,mBAAmB,gBAAgB,OAAO,KAAK,IAAI,CAAC,IAAI,CAAC;CAChG;AACF,CAAC,CACH"}
|
|
@@ -2,24 +2,27 @@ import * as Capabilities from "@dxos/app-framework/Capabilities";
|
|
|
2
2
|
import * as Capability from "@dxos/app-framework/Capability";
|
|
3
3
|
import { ClientCapabilities, ClientEvents } from "#types";
|
|
4
4
|
import * as Effect from "effect/Effect";
|
|
5
|
-
import { Client, ClientService } from "@dxos/client";
|
|
5
|
+
import { Client, ClientService, fromClient } from "@dxos/client";
|
|
6
|
+
import { BaseError } from "@dxos/errors";
|
|
6
7
|
import * as Plugin from "@dxos/app-framework/Plugin";
|
|
7
8
|
import { INITIALIZE_TIMEOUT } from "@dxos/client-protocol";
|
|
8
9
|
import * as Cause from "effect/Cause";
|
|
9
10
|
import { log } from "@dxos/log";
|
|
10
11
|
import * as Layer from "effect/Layer";
|
|
11
|
-
import { EffectEx } from "@dxos/effect";
|
|
12
12
|
import * as Exit from "effect/Exit";
|
|
13
|
+
import * as EffectEx from "@dxos/effect/EffectEx";
|
|
13
14
|
import { makeIdentityService, makeSpaceService } from "@dxos/halo-adapter-client";
|
|
14
15
|
//#region src/capabilities/client.ts
|
|
15
16
|
var __dxlog_file = "/__w/dxos/dxos/packages/plugins/plugin-client/src/capabilities/client.ts";
|
|
16
|
-
|
|
17
|
+
/** The client did not finish initializing inside the configured timeout. */
|
|
18
|
+
var ClientInitError = class extends BaseError.extend("ClientInitError", "Client failed to initialize.") {};
|
|
19
|
+
var client_default = Capability.makeModule(Effect.fnUntraced(function* ({ client: hostClient, onClientInitialized, onClientInitializationError, onSpacesAvailable, initializeTimeout = INITIALIZE_TIMEOUT, awaitInitialization = false, ...options }) {
|
|
17
20
|
const capabilityManager = yield* Capability.Service;
|
|
18
21
|
const pluginManager = yield* Plugin.Service;
|
|
19
22
|
log(hostClient ? "adopting host client" : "creating client", void 0, {
|
|
20
23
|
"~LogMeta": "~LogMeta",
|
|
21
24
|
F: __dxlog_file,
|
|
22
|
-
L:
|
|
25
|
+
L: 43,
|
|
23
26
|
S: this
|
|
24
27
|
});
|
|
25
28
|
const client = hostClient ?? new Client(options);
|
|
@@ -27,7 +30,7 @@ var client_default = Capability.makeModule(Effect.fnUntraced(function* ({ client
|
|
|
27
30
|
log("initializing client (forked)...", void 0, {
|
|
28
31
|
"~LogMeta": "~LogMeta",
|
|
29
32
|
F: __dxlog_file,
|
|
30
|
-
L:
|
|
33
|
+
L: 49,
|
|
31
34
|
S: this
|
|
32
35
|
});
|
|
33
36
|
let subscription;
|
|
@@ -35,14 +38,14 @@ var client_default = Capability.makeModule(Effect.fnUntraced(function* ({ client
|
|
|
35
38
|
log.info("client capability: destroying client", void 0, {
|
|
36
39
|
"~LogMeta": "~LogMeta",
|
|
37
40
|
F: __dxlog_file,
|
|
38
|
-
L:
|
|
41
|
+
L: 58,
|
|
39
42
|
S: this
|
|
40
43
|
});
|
|
41
44
|
subscription?.unsubscribe();
|
|
42
45
|
yield* Effect.tryPromise(() => client.destroy()).pipe(Effect.catch((error) => Effect.sync(() => log.warn("client destroy failed", { error: String(error) }, {
|
|
43
46
|
"~LogMeta": "~LogMeta",
|
|
44
47
|
F: __dxlog_file,
|
|
45
|
-
L:
|
|
48
|
+
L: 62,
|
|
46
49
|
S: this
|
|
47
50
|
}))));
|
|
48
51
|
}));
|
|
@@ -52,7 +55,7 @@ var client_default = Capability.makeModule(Effect.fnUntraced(function* ({ client
|
|
|
52
55
|
log("client.initialize() returned successfully", void 0, {
|
|
53
56
|
"~LogMeta": "~LogMeta",
|
|
54
57
|
F: __dxlog_file,
|
|
55
|
-
L:
|
|
58
|
+
L: 77,
|
|
56
59
|
S: this
|
|
57
60
|
});
|
|
58
61
|
if (onClientInitialized) yield* onClientInitialized({ client });
|
|
@@ -60,7 +63,7 @@ var client_default = Capability.makeModule(Effect.fnUntraced(function* ({ client
|
|
|
60
63
|
log("called client initialized callback", void 0, {
|
|
61
64
|
"~LogMeta": "~LogMeta",
|
|
62
65
|
F: __dxlog_file,
|
|
63
|
-
L:
|
|
66
|
+
L: 82,
|
|
64
67
|
S: this
|
|
65
68
|
});
|
|
66
69
|
yield* Plugin.activate(ClientEvents.Initialized);
|
|
@@ -73,20 +76,20 @@ var client_default = Capability.makeModule(Effect.fnUntraced(function* ({ client
|
|
|
73
76
|
log.info("client reconnected, reloading to re-establish session", void 0, {
|
|
74
77
|
"~LogMeta": "~LogMeta",
|
|
75
78
|
F: __dxlog_file,
|
|
76
|
-
L:
|
|
79
|
+
L: 108,
|
|
77
80
|
S: this
|
|
78
81
|
});
|
|
79
82
|
if (client.resetting) window.location.href = window.location.origin;
|
|
80
83
|
else window.location.reload();
|
|
81
84
|
});
|
|
82
|
-
let
|
|
85
|
+
let spacesAvailableFired = false;
|
|
83
86
|
subscription = client.spaces.subscribe(async () => {
|
|
84
|
-
if (!
|
|
85
|
-
|
|
87
|
+
if (!spacesAvailableFired) {
|
|
88
|
+
spacesAvailableFired = true;
|
|
86
89
|
performance.mark("milestone:spaces-ready");
|
|
87
90
|
const exit = await Effect.gen(function* () {
|
|
88
|
-
yield* Plugin.activate(ClientEvents.
|
|
89
|
-
if (
|
|
91
|
+
yield* Plugin.activate(ClientEvents.SpacesAvailable);
|
|
92
|
+
if (onSpacesAvailable) yield* onSpacesAvailable({ client });
|
|
90
93
|
}).pipe(Effect.provideService(Capability.Service, capabilityManager), Effect.provideService(Plugin.Service, pluginManager), Effect.runPromiseExit);
|
|
91
94
|
if (Exit.isFailure(exit) && !Cause.hasInterruptsOnly(exit.cause)) EffectEx.throwCause(exit.cause);
|
|
92
95
|
}
|
|
@@ -95,7 +98,7 @@ var client_default = Capability.makeModule(Effect.fnUntraced(function* ({ client
|
|
|
95
98
|
log.error("client initialization failed", { error: String(error) }, {
|
|
96
99
|
"~LogMeta": "~LogMeta",
|
|
97
100
|
F: __dxlog_file,
|
|
98
|
-
L:
|
|
101
|
+
L: 145,
|
|
99
102
|
S: this
|
|
100
103
|
});
|
|
101
104
|
if (onClientInitializationError) yield* onClientInitializationError({ error });
|
|
@@ -103,21 +106,25 @@ var client_default = Capability.makeModule(Effect.fnUntraced(function* ({ client
|
|
|
103
106
|
log("client capability ready (initialization in flight)", void 0, {
|
|
104
107
|
"~LogMeta": "~LogMeta",
|
|
105
108
|
F: __dxlog_file,
|
|
106
|
-
L:
|
|
109
|
+
L: 159,
|
|
107
110
|
S: this
|
|
108
111
|
});
|
|
109
112
|
const clientServiceLayer = awaitInitialization ? Layer.effect(ClientService, Effect.tryPromise({
|
|
110
113
|
try: () => client.waitUntilInitialized({ timeout: initializeTimeout }),
|
|
111
|
-
catch: (error) =>
|
|
112
|
-
|
|
114
|
+
catch: (error) => new ClientInitError({
|
|
115
|
+
context: { initializeTimeout },
|
|
116
|
+
cause: error
|
|
117
|
+
})
|
|
118
|
+
}).pipe(Effect.as(client))) : fromClient(client);
|
|
113
119
|
return [
|
|
114
120
|
Capability.contribute(ClientCapabilities.Client, client),
|
|
121
|
+
Capability.contribute(ClientCapabilities.InitializeTimeout, initializeTimeout),
|
|
115
122
|
Capability.contribute(Capabilities.Layer, clientServiceLayer),
|
|
116
123
|
Capability.contribute(ClientCapabilities.IdentityService, makeIdentityService(client)),
|
|
117
124
|
Capability.contribute(ClientCapabilities.SpaceService, makeSpaceService(client))
|
|
118
125
|
];
|
|
119
126
|
}));
|
|
120
127
|
//#endregion
|
|
121
|
-
export { client_default as default };
|
|
128
|
+
export { ClientInitError, client_default as default };
|
|
122
129
|
|
|
123
130
|
//# sourceMappingURL=chunk-client.mjs.map
|