Adapters
hot-updater adapter
The hot-updater adapter: host-wired download and error events plus client-side rollback() to the embedded bundle, with autoRollback support.
@release-health/adapter-hot-updater connects hot-updater to the
health engine. It reports the active bundle id and download and error events, and unlike the
expo-updates adapter it implements client-side rollback().
Install
npm install @release-health/adapter-hot-updater react-native-release-health @hot-updater/react-native@hot-updater/react-native is a peer dependency; the host app owns its version (0.35 or newer).
Usage
hot-updater delivers the id of a completed update through the onUpdateProcessCompleted callback
on HotUpdater.wrap (or HotUpdater.init), not through a subscribable event stream. Create the
adapter once, pass it to ReleaseHealth.init, and wire its callbacks into HotUpdater.wrap:
import { HotUpdater } from '@hot-updater/react-native';
import { ReleaseHealth } from 'react-native-release-health';
import { hotUpdaterAdapter } from '@release-health/adapter-hot-updater';
const adapter = hotUpdaterAdapter({ hotUpdater: HotUpdater });
ReleaseHealth.init({
adapter,
sinks: [
/* httpSink(...), ... */
],
});
function App() {
/* ... */
}
export default HotUpdater.wrap({
baseURL: '<your-update-server-url>',
updateStrategy: 'appVersion',
onUpdateProcessCompleted: adapter.onUpdateProcessCompleted,
onError: adapter.onError,
onNotifyAppReady: adapter.onNotifyAppReady,
})(App);Passing HotUpdater explicitly (rather than letting the adapter require it) also gives you a
compile-time check that your installed hot-updater version still matches the shape the adapter
expects.
When you reload to apply a downloaded update in the same session, tell the engine first:
ReleaseHealth.notifyReload();
await HotUpdater.reload();Behavior
- Events are host-wired. hot-updater's only public event,
onProgress, carries no bundle id, so the adapter cannot subscribe on its own. WireonUpdateProcessCompleted,onError, andonNotifyAppReadyas shown above. All three are safe to pass detached and never throw. downloadedfires once per new bundle id. A completedUPDATEis reported once; a repeat of the same id within a session is suppressed so the crash-loop counter is not reset.- Rollbacks are discriminated, not spurious. A fleet rollback (triggered from the hot-updater
console) reaches the client as
status: 'ROLLBACK', which the adapter does not report as a download. Your event stream never shows a rollback as a phantomupdate_downloaded. - Client-side rollback. The adapter implements
rollback(), which reverts to the embedded bundle through hot-updater'supdateBundle. SetautoRollback: trueonReleaseHealth.initto revert automatically when a crash loop is detected.rollback()stages the revert; it does not reload, so the embedded bundle takes effect on the next launch (or callHotUpdater.reload()yourself afterReleaseHealth.notifyReload()). Client rollback saves the device, not the fleet: until the release is disabled server-side, the next update check downloads the bad bundle again. Treat automatic rollback as first aid and disable the release at the source; see Limitations. - Degrades gracefully. When hot-updater is missing or its native module is unavailable
(development, misconfiguration), the adapter reports the embedded bundle, emits no events, omits
rollback(), and logs a single warning. It never throws into the host app.
Works with hot-updater's built-in crash detection
hot-updater ships its own native crash guard: it verifies a newly installed bundle on the first
launch and automatically reverts to a working bundle if startup fails before the first frame.
release-health covers the complementary window, from the first frame until your app calls
markHealthy(), where the update rendered but the app is not actually usable.
The two fit together:
- A crash before the first frame is handled by hot-updater. It reverts the bundle and reports
it through
onNotifyAppReadyas{ status: 'RECOVERED', crashedBundleId }; the adapter surfaces that as anerrorfor the reverted bundle so your sinks record the failed apply. - A crash or hang after the first frame, before
markHealthy(), is handled by release-health: the update goes on probation, consecutive failed launches trip the crash-loop threshold, andonRollbackRecommendedfires (andautoRollbackreverts, if enabled).
Options
| Option | Default | Description |
|---|---|---|
hotUpdater | require('@hot-updater/react-native').HotUpdater | Alternative module implementation (tests, custom wrappers) |
warn | console.warn | Warning channel |