client library
The app foundation: the OmnyShell service facade, state primitives, storage and routing.
Everything a browser app needs around the terminal, with no DOM framework and no app-specific coupling:
- OmnyShellService — the only thing that touches omnyshell's
ClientRuntime. It normalizes Hub URLs, translates exceptions into AppErrors, and exposes connect / nodes / sessions / shell operations. AConnectionFactorycan be injected to drive it against a fake Hub in tests. - Observable and AsyncState — the state model. Controllers own observables
of immutable snapshots; screens subscribe and re-render their own subtree.
AsyncStatedeliberately keepsdatawhileloadingor inerror, so the UI can show last-known content under a spinner or a banner. - KeyValueStore / SettingsStore / NodeCache — persistence, behind an
interface so the logic is testable on the VM. Pass your own
prefix:localStorageis per-origin and one Hub can serve two apps, which would otherwise clobber each other's theme, Hub and token. - Router — hash-based (
#/path), so the app deploys as static files with no server rewrites.matchRouteis pure and VM-testable. - ThemeController — light/dark/system, DOM-free (application is injected), so the pre-paint theme script can drive it without a flash.
The domain types themselves (NodeDescriptor, RemoteSession, Principal, …)
come from package:omnyshell/omnyshell_client_web.dart.
Note the split: the DOM-free half of this lives in foundation.dart, which
this re-exports. A consuming app's service and controller layers should
import that — it runs on the VM, so they stay unit-testable with
dart test instead of needing headless Chrome. Only what actually touches
the page (LocalStorageStore, Router) needs this library.
Classes
- ActionResult
- The outcome of a session action (kill/detach), surfaced to the UI as a toast.
- AiSettingsController
- Owns the user's AI preferences, persisting each change to SettingsStore and exposing the Hub's advertised default for the settings panel.
-
AsyncState<
T> - An immutable snapshot of an asynchronous value with explicit loading/error states — the shape every data screen renders. Carries optional data even while LoadStatus.loading or LoadStatus.error so the UI can show last-known content (e.g. cached nodes) under a spinner or error banner.
- AuthController
- Orchestrates login/logout and session persistence between the OmnyShellService and the SettingsStore, exposing an observable AuthSnapshot for the UI.
- AuthSnapshot
- An immutable snapshot of auth state, rendered by the UI.
- KeyValueStore
-
A minimal synchronous string key/value store. Abstracts
localStorageso that storage-backed logic can be unit-tested with MemoryKeyValueStore without a browser. - LocalStorageStore
-
A KeyValueStore backed by the browser's
window.localStorage. - MemoryKeyValueStore
- An in-memory KeyValueStore for tests and non-browser contexts.
- NodeCache
-
Caches the last-known node list so the nodes screen can paint instantly on
reload while a fresh fetch runs. Backed by KeyValueStore; the cache is
best-effort — any decode error yields
null(treated as a cold cache). - NodesController
- Loads and holds the discoverable node list, with cache-backed instant paint and explicit loading/error states.
-
Observable<
T> - A minimal observable value: holds a current value and notifies listeners on change via a broadcast stream. The web app's lightweight alternative to a state-management framework — screens subscribe and re-render their DOM subtree when the value changes.
- OmnyShellService
-
A thin facade over the OmnyShell
ClientRuntimethat the UI talks to. - PeekResult
- A captured session screen, decoded to text for display.
- RouteMatch
-
A matched route: the pattern that matched, the concrete path, and any
extracted path params (e.g.
/nodes/:idagainst/nodes/web-01yields{id: web-01}). - Router
-
Hash-based router (
#/path) — needs no server rewrites, so the app hosts as pure static files. Holds the current match observable and translates browserhashchangeevents into route updates. The matching logic lives inroute_match.dart(DOM-free, unit-tested on the VM). - SessionsController
- Loads and acts on the sessions of a single node: list, kill, detach, peek. Created per sessions-screen instance (sessions are per-node and ephemeral).
- SettingsStore
- Typed, namespaced access to persisted app settings over a KeyValueStore.
- TerminalDisplayController
- Owns the user's terminal display preferences — the dimension preset (and the custom column/row values it uses) and the text size — persisting each change and exposing them as observables the settings panel and session screen watch.
- ThemeController
-
Owns the theme mode, persists it, and exposes the resolved theme that the
UI applies as
data-themeon the document root.
Enums
- AppErrorKind
- A user-facing error category, mapped from the lower-level OmnyShell exceptions so the UI can show a tailored message and recovery hint without switching on raw exception types everywhere.
- AuthStatus
- Where the user is in the authentication lifecycle.
- LoadStatus
- Where an async load currently stands.
- ResolvedTheme
- The concrete theme applied to the document: only light or dark.
- ThemeMode
- The user's theme preference.
Functions
-
hashToPath(
String hash) → String -
Normalizes a URL hash (
#/foo) to a path (/foo); empty hash →/. -
matchRoute(
List< String> patterns, String path) → RouteMatch -
Matches
pathagainstpatterns, returning the first match. Patterns use:namesegments for parameters. Pure and DOM-free. -
relativeTime(
DateTime time, DateTime now) → String -
Formats
timeas a compact relative age fromnow(e.g.5m ago,2h ago,3d ago). Pure for unit testing — the live caller passesDateTime.now(). -
untilExpiry(
DateTime expiresAt, DateTime now) → String -
Formats a Duration until expiry as
in 5m/in 2h/expired.
Exceptions / Errors
- AppError
- A normalized error with a human-readable message and an optional recovery hint. Built from any thrown object via AppError.from.