a28eb78ded
Keep local/offline and host capability recipes on app-owned command/event/projection flow without teaching raw EffectBatch as the authoring boundary. req: local/001 req: local/002 req: host/002
70 lines
2.4 KiB
Markdown
70 lines
2.4 KiB
Markdown
# Recipe: typed host capabilities
|
|
|
|
`hemx-host` is the boundary between a hemx app and a browser, PWA,
|
|
WebView, or native shell. It is not a mobile framework and it is not a new UI
|
|
runtime. A host adapter can perform explicit host side effects or return facts;
|
|
app code still owns domain decisions and returns normal hemx effects. req: host/001 req: host/002
|
|
|
|
## Contract
|
|
|
|
Declare the capability shape the app may use:
|
|
|
|
```rust
|
|
use hemx_host::{Capability, CapabilityManifest, CapabilityShape, CapabilityUse};
|
|
|
|
let manifest = CapabilityManifest::new([
|
|
CapabilityUse::new(Capability::Haptics, CapabilityShape::Fire),
|
|
CapabilityUse::new(Capability::Share, CapabilityShape::Request),
|
|
]);
|
|
```
|
|
|
|
Check the manifest against the concrete host profile before executing calls:
|
|
|
|
```rust
|
|
use hemx_host::{HostProfile, HostCheckError};
|
|
|
|
let host = HostProfile::new(
|
|
"web",
|
|
[CapabilityUse::new(Capability::Share, CapabilityShape::Request)],
|
|
);
|
|
|
|
let result: Result<(), HostCheckError> = manifest.check(&host);
|
|
```
|
|
|
|
Permission-sensitive capabilities such as microphone, camera, notifications,
|
|
secure storage, file picker, and geolocation need a user-facing reason in the
|
|
manifest before standard host checks pass. req: host/003 req: host/004
|
|
|
|
## Browser/PWA adapter
|
|
|
|
`hemx-host::BROWSER_HOST_JS` is an optional tiny browser adapter. It exposes
|
|
`window.hemxBrowserHost.perform(call)`, accepts the serde JSON shape of
|
|
`HostCall`, calls browser APIs such as `navigator.share` or `navigator.vibrate`,
|
|
and returns the serde JSON shape of `HostEvent`. It does not query, patch, or
|
|
own the DOM; the app consumes the host event and returns ordinary hemx effects.
|
|
req: host/001 req: host/002 req: host/005
|
|
|
|
## Event flow
|
|
|
|
Host events are facts, not app mutations. Denied, timeout, unavailable, and
|
|
error cases all use `HostEvent::Failed(HostFailure { kind, ... })`, so app code
|
|
handles one typed result shape before producing UI effects:
|
|
|
|
```text
|
|
HostEvent
|
|
→ app/domain command
|
|
→ domain validation and optional persistence
|
|
→ projection/rendering
|
|
→ generated UI effects
|
|
```
|
|
|
|
Adapters must not mutate DOM, append domain events, or write application state
|
|
on behalf of the app. req: host/002 req: host/005
|
|
|
|
## Mobile
|
|
|
|
iOS and Android shells are thin host adapters around a WebView. They implement
|
|
manifest-backed calls such as haptics, share, microphone streams, secure
|
|
storage, notifications, and explicit custom capabilities; hemx still owns UI
|
|
effects and the app still owns state. req: host/001 req: host/002
|