JSPM

@orion-ehr/app-bridge

0.0.2
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 8
  • Score
    100M100P100Q114016F
  • License MIT

Embedded-app SDK for the Orion EHR App Bridge. Provides React hooks and a postMessage protocol client for iframe apps to communicate with the Orion host.

Package Exports

  • @orion-ehr/app-bridge

Readme

@orion-ehr/app-bridge

Embedded-app SDK for the Orion EHR App Bridge. React hooks and a postMessage protocol client for iframe apps to communicate with the Orion host.

Status: pre-1.0. The API is not yet stable; pin exactly ("@orion-ehr/app-bridge": "0.0.1", not "^0.0.1"). Phase 1 of the App Bridge Parity Initiative.

Install

npm install @orion-ehr/app-bridge

Peer dependencies: React 18+ or 19+.

Usage

Wrap your entry point in <OrionProvider>:

import { OrionProvider } from '@orion-ehr/app-bridge';
import App from './App';

export default function bootstrap(ctx: OrionAppContext) {
  return (
    <OrionProvider appId={ctx.appId} initialContext={ctx}>
      <App />
    </OrionProvider>
  );
}

Then use the typed hooks anywhere inside the subtree:

import {
  useTheme,
  usePatient,
  useEncounter,
  useToast,
  useNavigate,
  useAutoResize,
  useHostInfo,
} from '@orion-ehr/app-bridge';

function MyApp() {
  const theme = useTheme();
  const patient = usePatient();
  const encounter = useEncounter();
  const showToast = useToast();
  const navigate = useNavigate();
  const hostInfo = useHostInfo();

  useAutoResize();

  return (/* ... */);
}

Surfaces

Hook Purpose
useOrion() Live bridge instance + full app context
useOrionContext() Live OrionAppContext only (re-renders on context change)
useTheme() Current ThemeMessage (mode + tokens)
useUser() Currently-signed-in user
usePatient() Currently-active patient (or null)
useEncounter() Currently-active encounter (or null)
useTokenResponse() SMART access token + launch context
useToast() Stable showToast(message, type, duration?) callback
useNavigate() Stable navigate(url, options?) callback
useHostInfo() Host origin, tenant domain, protocol version (cached)
useAutoResize() Wires a ResizeObserver to post content height to host
useBridge() Direct OrionBridge instance for advanced uses

Theming

The host pushes resolved CSS custom properties (--background, --primary, etc.) on every theme/mode change. <OrionProvider> applies them to the iframe document's :root automatically. Apps using @orion-ehr/ui's Tailwind classes (bg-background, text-primary, etc.) inherit the host's theme without any per-app theming code.

For light/dark mode: the provider toggles dark on documentElement to match the host's resolved mode. Tailwind dark: variants and the UI library's mode-scoped tokens both pick this up.

Architecture

OrionBridge is the postMessage transport (request/response correlation, event subscription, timeouts). <OrionProvider> constructs a single bridge instance per iframe, holds the live OrionAppContext, applies tokens, and subscribes to host events that update context. Hooks read the React context and return slices of it.

Wire protocol matches the host's app-bridge/message-handler.ts. See docs/marketplace.md for protocol-level details.

Errors

Bridge requests that fail throw BridgeRequestError with a code field:

Code Meaning
UNSUPPORTED_ACTION Host doesn't recognize the action (older host, capability not granted)
PERMISSION_DENIED Host recognized the action but rejected it (revoked install, missing scope)
INTERNAL Host hit an unexpected error
TIMEOUT SDK timed out waiting for a host response

Branch on error.code rather than parsing error.message. Free-form host error strings are mapped to a code (UNSUPPORTED_ACTION for legacy "Unknown action" / "does not support" wording, INTERNAL otherwise) with a single console.warn recommending the host upgrade to structured codes — that fallback will be removed once the host wire-shape ships { code, message } consistently.

FHIR REST helpers

bridge.fhirFetch(path, init?) issues authenticated FHIR REST calls against the host-minted SMART token + tenant FHIR base URL. Convenience helpers: getResource, searchResources, createResource, updateResource, deleteResource.

Security guarantees:

  • The resolved request URL must share an origin with fhirBase. Absolute URLs and protocol-relative paths (//evil.example) are rejected before the request is sent.
  • redirect: 'error' is forced on every request so a host-side 3xx can't pull the bearer off-origin.
  • Error messages do not include the response body by default, since FHIR OperationOutcome payloads routinely contain PHI. Pass new OrionBridge({ debug: true }) (dev only) to opt into body inclusion.
  • bridge.destroy() clears fhirAccessToken / fhirBase so the bearer doesn't survive teardown in heap snapshots.

License

MIT — see LICENSE.