@hyperfrontend/features/hostee

Hostee

Hostee-side SDK for feature apps — feature initialization, contract declaration, and lifecycle.

import { createFeature } from '@hyperfrontend/features/hostee'

const feature = createFeature({
  name: 'clock',
  contract: {
    emitted: [{ type: 'tick' }],
    accepted: [{ type: 'set-timezone' }],
  },
})

await feature.ready()
feature.on('set-timezone', ({ tz }) => render(tz))
setInterval(() => feature.send('tick', Date.now()), 1000)

API

ExportPurpose
createFeatureConnect a feature app to its host; returns send/on/ready/close.
FeatureHandleType of the handle returned by createFeature.

ready() resolves once the wire handshake with the host completes, and rejects if the host does not open the connection within readyTimeoutMs (default 10 s; an error with reason: 'ready-timeout' is also emitted). Sends issued before the handshake completes queue and flush on open. send emits a contract action to the host; on subscribes to host messages and the open/closing/close/error/presentation/resize lifecycle events (closing is the flush window before a polite close completes). setDirty declares unsaved work to the host. close disconnects from the host politely.

Presentation

The host owns how the feature is surfaced; the SDK receives that decision and prepares the document, so the app author only has to make the layout responsive.

Right after open, the host announces the display mode along with the frame's initial dimensions — read the mode from feature.displayMode or the presentation event ({ mode }); the dimensions arrive as the first resize event, no extra round trip. In the iframe modes the host then reports every change to the frame's usable space as exact pixels; the SDK sizes html/body to match and re-emits each as resize ({ width, height }). In popup/standalone the browser window is the viewport and resize comes from the feature's own window. Responding to the reported width and height — media/container queries, reflow, breakpoints — is the app author's job.

In dialog mode the frame spans the host's viewport, transparent. The SDK places your root element (the body's first element child, or pass root to createFeature) at the agreed position — centered by default — and sizes it to the agreed inner-box dimensions; everything around it is the backdrop. You style the box itself — background, border, shadow — since an unstyled box is invisible against the transparent backdrop. The SDK detects pointer interaction on the bare backdrop and Escape presses and reports them to the host as dismiss signals — pure reports: the SDK tears nothing down itself, and if the host's policy is to close, the ordinary polite close (closing flush window included) follows. Because the pane covers the whole viewport, dragging or resizing the box is ordinary in-document CSS/pointer work if you want it — nothing crosses the boundary.

The body reset (resetBody, on by default) keeps html/body margin-free and transparent, with a color-scheme pin matched to the host frame — overriding the background or color-scheme with an opaque/dark scheme breaks the transparency that embedded blending and dialog backdrops depend on.

It applies on a standalone visit too, and its stylesheet is injected when createFeature runs — landing after the page's own stylesheet and winning at equal specificity. So paint the feature's background on its root layout element, never on body; a body { background: … } rule silently loses to the reset. Pass resetBody: false to opt out entirely and own the reset yourself.

API Reference

ƒ Functions

§function

createFeature(options: FeatureOptions): FeatureHandle

Initializes a feature app on the hostee side and waits for the host connection.
Creates a nexus broker for the feature, resolves the host window, and returns a handle for messaging and lifecycle. When protocol selects the v1 or v2 envelope, the feature negotiates it with the host during the connection handshake and messages travel encrypted once it opens. A version announces the contract cut this feature holds (overriding any contract.version), so the handshake can deny hosts built against an incompatible cut.

Parameters

NameTypeDescription
§options
FeatureOptions
Feature name, contract, and optional version, root-element, and security settings.

Returns

FeatureHandle
A handle exposing send, on, ready, and close.

Example

Initializing a clock feature

const feature = createFeature({ name: 'clock', contract, version: '1.2.0', protocol: 'v2', sharedKey: 'pre-shared-key' })
feature.ready().then(() => feature.send('timeUpdated', { time: Date.now() }))
feature.on('setTimezone', (data) => console.log(data))

Interfaces

§interface

FeatureHandle

Public handle returned by the hostee-side feature factory.

Properties

§readonly displayMode:DisplayMode
The display mode the host announced for this mount, or null before the announcement arrives (it is the first message after open) and after the channel closes.
§interface

ActionDescription

Description of a single action a feature can emit or accept.
Structurally compatible with nexus's channel contract action shape so the same contract can drive both messaging and the shell type generator.

Properties

§description?:string
Human-readable explanation of the action, surfaced in tooling.
§required?:boolean
Marks an accepted action as essential for correct operation: the connection is denied at handshake time unless the counterpart emits this type. Only meaningful on accepted entries. Unflagged actions never gate the connection, so additive contract evolution stays non-breaking.
§respondsWith?:string
When this action is used as a request, the type of the action in the other direction that answers it.
§schema?:object
Optional JSON-schema-like shape describing the action payload.
§type:string
Wire type string that identifies the action.
§interface

FeatureContract

The set of actions a feature emits to, and accepts from, its counterpart.
This is the same shape the on-disk *.contract.json files and the shell generator consume.

Properties

§accepted:ActionDescription[]
Actions this side handles from the other side.
§emitted:ActionDescription[]
Actions this side sends to the other side.
§version?:string
Optional semver version announcing the contract cut this side holds. Builds canonicalize and bake it into the generated shell; the two sides compare their announcements during the connection handshake and incompatible cuts are denied before the channel opens. Absent on either side, the check passes, so unversioned peers keep connecting.
§interface

FeatureOptions

Options accepted by the hostee-side feature factory.

Properties

§contract:FeatureContract
Contract describing the actions the feature emits and accepts.
§name:string
Stable identifier for the feature, used to name its messaging channel.
§protocol?:SecurityProtocol
Security envelope to negotiate with the host; defaults to none.
§readyTimeoutMs?:number
Milliseconds the feature waits for the host to complete the connection handshake before ready() rejects and an error with reason: 'ready-timeout' is emitted; defaults to 10000.
§resetBody?:boolean
Whether to neutralize the feature page's html/body; defaults to true. Zeroes margin and padding, forces background: transparent, and pins color-scheme: normal — on a standalone visit too, and injected late enough to outrank the page's own body rules, so paint the feature's background on its root layout element instead.
§root?:string | HTMLElement
The feature's root layout element (or a CSS selector for it); defaults to the body's first element child. In dialog mode the hostee SDK centers this element inside the full-viewport pane and applies the agreed inner dialog box dimensions to it; the area around it is the backdrop.
§sharedKey?:string
Pre-shared key used by the v2 protocol.
§version?:string
Semver version of the contract cut this feature holds; takes precedence over contract.version.
§interface

RequestOptions

Per-request settings accepted by request.

Properties

§timeoutMs?:number
Milliseconds to wait for the response before rejecting; defaults to 30000.
§interface

ViewportPayload

Payload of the reserved viewport control message: the exact pixel dimensions of the space the feature's frame occupies, reported by the host whenever the measured space changes (iframe modes only).

Properties

§height:number
Usable height in pixels.
§width:number
Usable width in pixels.

Types

§type

EventHandler

Handler invoked when a subscribed event fires.
type EventHandler = (data: unknown) => void
§type

RequestHandler

Answers one request type; may return the response value directly or a promise of it.
type RequestHandler = (data: unknown) => unknown
§type

SecurityProtocol

Union of the supported security envelope selectors.
none is the local default (opt-in security); production builds must pick v1 or v2.
type SecurityProtocol = "none" | "v1" | "v2"

Variables

§type

DisplayMode

Supported ways a host can surface an embedded feature.
The host selects the mode; a feature declares which modes it supports in its feature.config.* display.modes, and the generated shell composes exactly those.