Runtime APIs
What the Runtime APIs Are
The runtime APIs are the lower-level functions behind Bundle Drop's update behavior.
They are useful when you want direct control over checking, downloading, applying, channel discovery, or user-property management.
Start by calling BundleDrop.init once. After that, these APIs use the active runtime channel and environment managed by the singleton runtime.
If you prefer a React hook wrapper for manual UI flows, use useBundleDrop.
Runtime Controller
BundleDrop.init({ environment, enabled?, channelName?, policy?, onStatusUpdate?, checkOnly? })
Initializes the runtime for the current app process.
environmentis requiredenableddefaults totruechannelNamesets the initial active channelpolicycontrols startup behavior
BundleDrop.setChannel(channelName)
Changes the active runtime channel for subsequent checks, downloads, applies, and hook-driven OTA actions.
BundleDrop.getChannelName()
Returns the current active runtime channel outside React.
Core Update Functions
checkForUpdate(onStatusUpdate?)
Checks for an update decision and returns:
Promise<
| {
action: "NOOP";
upToDate?: boolean;
channelName?: string;
reason?: string;
incompatible?: boolean;
requestedRuntimeVersion?: string;
latestRuntimeVersionOnChannel?: string;
}
| {
action: "INSTALL";
upToDate?: false;
channelName?: string;
hash?: string;
downloadUrl?: string;
bundleVersion?: number;
version?: string;
runtimeVersion?: string;
}
| {
action: "ROLLBACK";
channelName?: string;
reason?: string;
}
| null
>
Use it when you want to check availability without downloading immediately. It uses the currently active runtime channel.
useBundleDrop().checkLatest() wraps this for hook-based flows.
downloadUpdate(onStatusUpdate?)
Downloads and stages an update, and returns:
Promise<
| { status: "staged"; bundlePath: string; hash: string }
| { status: "upToDate" }
| { status: "disabled" }
| { status: "incompatible" }
| { status: "rollback"; reason?: string }
>
Use it when you want to fetch the update but choose separately when to apply it. It uses the currently active runtime channel.
useBundleDrop().downloadUpdate() wraps this for hook-based flows.
applyUpdate(onStatusUpdate?)
Applies a staged update and returns:
Promise<
| { status: "applied" }
| { status: "noBundle" }
| { status: "disabled" }
| { status: "alreadyApplied" }
>
Use it when you want to explicitly trigger application after a bundle has already been downloaded.
useBundleDrop().applyUpdate() wraps this for hook-based flows.
getUpdateState()
Returns:
Promise<{
hasBundle: boolean;
info: BundleInfo | null;
pendingApply: boolean;
}>
This is useful when your UI needs to know whether a bundle exists locally and whether it is waiting to be applied.
getInstalledBundleInfo()
Returns:
Promise<BundleInfo | null>
Use it when you only need the installed bundle metadata and do not need the full update state wrapper.
Channel Discovery
getAvailableChannels()
Returns:
Promise<string[]>
This fetches the list of public channel names for the configured project.
useBundleDrop().fetchAvailableChannels() exposes the same capability in hook form and stores the result in availableChannels.
Configuration
bundleDropConfig
A read-only object that exposes the resolved project configuration for the current device. Useful for displaying runtime info in dev tools, debug screens, or support dialogs without manually importing and parsing the config file.
import { bundleDropConfig } from "@gfean/react-native-bundle-drop";
Shape:
{
serverUrl: string;
platform: "ios" | "android";
runtimeVersion: string | undefined;
defaultChannel: string;
org: { slug: string };
project: { name: string; slug: string };
debugLocal: boolean;
rollback: {
maxCrashCount: number;
crashWindowSec: number;
commitTimeoutSec: number;
};
}
Values are resolved at module load from your bundle.drop.config.js. The platform and runtimeVersion fields are already resolved for the current device — no need to check Platform.OS yourself.
The apiKey is intentionally excluded from this object.
The BundleDropConfig type is also exported for TypeScript consumers:
import type { BundleDropConfig } from "@gfean/react-native-bundle-drop";
Bundle Browsing and Manual Install
These functions let users browse available bundles on a channel and install a specific version. This is useful for building custom version-picker screens, QA tools, or rollback UIs inside your app.
Bundle Drop handles the download and staging. Your app handles the UI.
getAvailableBundles(options?)
Fetches a paginated list of downloadable bundles for a channel and returns:
Promise<{
items: BundleListItem[];
nextCursor: string | null;
hasMore: boolean;
}>
Each BundleListItem contains:
{
hash: string;
bundleVersion: number;
version: string;
platform: string;
runtimeVersion: string;
releaseNotes: string | null;
createdAt: string;
downloadUrl: string | null;
}
Options:
channelName: defaults to the active runtime channelplatform: defaults to the current device platformlimit: number of items per page (1–50, default 20)cursor: pagination cursor from a previous response'snextCursor
Only non-expired bundles with available storage are returned. Results are sorted newest first.
useBundleDrop().fetchBundles() wraps this for hook-based flows.
installBundle(hash, downloadUrl, bundleVersion?, version?, runtimeVersion?, onStatusUpdate?)
Downloads and stages a specific bundle by its hash and download URL. Returns the same shape as downloadUpdate:
Promise<
| { status: "staged"; bundlePath: string; hash: string }
| { status: "upToDate" }
| { status: "disabled" }
| { status: "incompatible" }
| { status: "rollback"; reason?: string }
>
This uses the same download and install pipeline as regular OTA updates. After calling installBundle, call applyUpdate() to reload with the selected bundle.
useBundleDrop().installBundle(bundleListItem) wraps this for hook-based flows and accepts a BundleListItem directly.
Typical usage
1import {
2 BundleDrop,
3 getAvailableBundles,
4 installBundle,
5 applyUpdate,
6} from "@gfean/react-native-bundle-drop";
7
8BundleDrop.init({
9 environment: "staging",
10 channelName: "production",
11 policy: "manual",
12});
13
14// Fetch first page of bundles
15const page = await getAvailableBundles({
16 limit: 10,
17});
18// page.items, page.hasMore, page.nextCursor
19
20// Fetch next page
21const page2 = await getAvailableBundles({
22 cursor: page.nextCursor,
23});
24
25// User picks a bundle
26const selected = page.items[3];
27await installBundle(
28 selected.hash,
29 selected.downloadUrl,
30 selected.bundleVersion,
31 selected.version,
32 selected.runtimeVersion,
33);
34
35// Apply the selected version
36await applyUpdate();User Property Functions
These functions manage key-value user properties on the device. They are used for Targeted Rollout and audience estimation.
Both keys and values are case-sensitive. "tier" and "Tier" are treated as different keys.
All values must be strings. Non-string types (booleans, numbers) are rejected by the server. Pass them as strings instead (e.g. "true", "42").
setUserProperty(key, value)
Sets a key-value property for the current app install and returns:
Promise<Record<string, string>>
The returned object is the full set of user properties after the change. If the key already has the same value, the call is a no-op.
removeUserProperty(key)
Removes a property by key and returns:
Promise<Record<string, string>>
The returned object is the full set after removal.
getUserProperties() / getCurrentUserProperties()
Each returns:
Promise<Record<string, string>>
Use these when you need to inspect the currently stored properties.
resetUserProperties()
Returns:
Promise<void>
Use it when you want to clear all user properties for the current app install.
Hook vs Direct Functions
A practical way to choose:
- use useBundleDrop when building manual React UI
- use direct runtime functions when you want lower-level control
- use BundleDrop.init when you want automated startup handling or shared runtime state
Some direct runtime functions are also surfaced through the hook:
checkForUpdate->useBundleDrop().checkLatest()downloadUpdate->useBundleDrop().downloadUpdate()applyUpdate->useBundleDrop().applyUpdate()getAvailableChannels->useBundleDrop().fetchAvailableChannels()getAvailableBundles->useBundleDrop().fetchBundles()installBundle->useBundleDrop().installBundle()
Related Docs
- For runtime startup setup, see BundleDrop.init.
- For manual UI-driven flows, see useBundleDrop.
- For policy behavior, see Update Policies.
- For audience targeting, see Targeted Rollout.