Standalone operation
Standalone is what the dashlet becomes when it runs outside any enaio environment — a plain browser tab, a dev server, or any non-enaio embed: no bridge, no events. It is a first-class state, not a failure.
1. How standalone is reached
There is no explicit flag. The detection state machine (see
Environments and detection) simply times out:
when no rich-client bridge and no accepted webclient event arrive within
the detection cap (detectionTimeoutMs, default 5000 ms), the dashlet
settles as standalone. It is never a hang — the state is reached in
bounded time, and it is observable through the normal init promise.
Two further corners arrive at the same state:
-
Top-level window, no configured origin: origin learning only works inside an iframe. A top-level window that has no configured origin never learns and degrades to standalone after the detection cap (see Origin configuration).
-
Foreign-origin host: a webclient-style
onInitposted from an origin that fails validation is rejected; nothing initializes, and the dashlet degrades to standalone within the same bounded cap.
2. What a standalone dashlet does
| Surface | Behavior |
|---|---|
|
Resolves exactly once and never rejects, with
|
|
Registered normally; they replay the standalone init and never fire updates |
|
Rejects with the bounded |
All seven portable facade methods |
Same as |
The rule for dashlet code: render a fallback instead of waiting. The
init promise is the place to branch — if ctx.environment ===
'standalone', show your offline/degraded UI and don’t await any host
call.
3. The timeout mechanics
Every host interaction that awaits a reply is bounded: the init wait by the
detection cap (detectionTimeoutMs, default 5000 ms) plus a 250 ms safety
net, every method call by the response timeout (timeoutMs, default 5000
ms). A timeout rejects with the distinct
TimeoutError (error name DashletTimeoutError, carrying the operation
and the timeout it hit), so dashlet code can distinguish "host never
answered" from any other failure:
import { TimeoutError } from 'ecmind-blue-dashlet';
await dashlet.openIndexData({ inNewTab: false, mode: 'view', objectId: '1024' })
.catch((e) => {
if (e instanceof TimeoutError) {
showFallback(); // standalone or a dead host — no retry loop
}
throw e;
});
The enaio contract defines no response guarantee; the bound is what makes "no response" an observable state.
4. Tuning the knobs
From DashletOptions:
| Option | Default | Standalone-relevant meaning |
|---|---|---|
|
|
Detection cap: how long the dashlet probes for a bridge / waits for an
|
|
|
Response timeout for every method call — in standalone, this is how
quickly each facade call rejects with |
|
|
Rich-client bridge poll interval (no effect on standalone, but part of the same tuning story: a late bridge is caught by polling within the detection cap) |