SDK API reference
Look up public exports, defaults, hooks, check results and error contracts.
Updated 2026-09-14
On this page
- Overview
- Client class
- ClientOptions
- React integration
- CheckResult and version info
- Metadata and crash correlation
- Errors and events
- checkUpdate(params?)
- downloadUpdate(info?)
- downloadAndInstallApk(url)
- markSuccess()
- currentVersionInfo
- getCurrentVersionInfo()
- restartApp()
- resetToPackagedBundle(options?)
- switchVersion(info?)
- switchVersionLater(info?)
- parseTestQrCode(code)
- useUpdateProgress()
- dismissError()
- Build a custom update UI
- Check, download and reload hooks
- Native startup checks
- captureException(error, context?)
- Android mixed apps: setCustomInstanceManager
Complete the minimal integration first. Use this page to look up options; you do not need every option. Reuse one client instance for reporting and configuration.
Overview
All public APIs of the Pakta SDK (npm package rn-update) are exported from the package entry. Five groups:
The
Paktaclient class andClientOptionsThe
UpdateProvider(aliasPaktaProvider) React integrationThe
useUpdate()/useUpdateProgress()/usePakta()hooksUpdate metadata and crash-report correlation
The
UpdateErrortype and the event model
Client class
import { Pakta } from 'rn-update';
const client = new Pakta({
appKey: '<your appKey>',
updateStrategy: 'silentAndLater',
});
// Update configuration at runtime (idempotent merge; re-renders the Provider)
client.setOptions({ checkStrategy: 'onAppResume' });
// Manually report a JS exception (global ErrorUtils is chained automatically)
client.captureException(error, { context: 'checkout' });ClientOptions
| Field | Type | Default | Description |
|---|---|---|---|
appKey | string | required | Platform appKey assigned by the console |
server | { main: string[]; queryUrls?: string[] } | official endpoints | Self-hosted service address and endpoint discovery list |
updateStrategy | see below | 'alertUpdateAndIgnoreError' | Prompt and activation strategy |
checkStrategy | 'onAppStart' | 'onAppResume' | 'both' | null | 'both' | Check timing; null disables JS auto-check |
autoMarkSuccess | boolean | true | Auto-confirm the running version as healthy |
autoMarkSuccessDelayMs | number | 1000 | Auto-confirm delay; raise when critical modules load late |
healthCheck | () => boolean | Promise<boolean> | — | Health gate before confirming; false skips this launch |
maxRetries | number | 3 | Download retry count |
logger | ({ type, data }) => void | — | Update event logger |
locale | 'zh' | 'en' | 'zh' | Built-in prompt language |
debug | boolean | false | Verbose internal logs |
throwError | boolean | false | Throw update errors to JS |
testChannel | boolean | true | Honor test QR codes/deep links; use false in production |
beforeCheckUpdate / afterCheckUpdate | hooks | — | Around every check |
beforeDownloadUpdate / afterDownloadUpdate | hooks | — | Around every download |
beforeReload | (ctx: { type: 'switchVersion' | 'restartApp' }) => … | — | Before reload |
onPackageExpired | hook | — | Overrides the expired-package default behavior |
disableTelemetry | boolean | false | Disable client telemetry and JS error transport |
disableErrorReporting | boolean | false | Disable JS error reporting only |
updateStrategy values: 'silentAndNow', 'silentAndLater', 'alertUpdateAndIgnoreError', 'alwaysAlert'.
React integration
import { Pakta, UpdateProvider, PaktaProvider, useUpdate, usePakta, useUpdateProgress } from 'rn-update';UpdateProvider/PaktaProvider(alias) — takes aclientprop; mounting a second provider in the same process throws.useUpdate()— update state and actions (below).useUpdateProgress()— isolated download progress{ hash, received, total, progress? }.usePakta()— an alias ofuseUpdate(), returning the same state and actions; access the instance throughuseUpdate().client.
UpdateContextValue returned by useUpdate():
| Member | Description |
|---|---|
updateInfo | Last CheckResult |
lastError | Last error |
currentHash / packageVersion | Active update hash and native package version |
currentVersionInfo | { name?, description?, metaInfo? } |
checkUpdate(params?) | Manual check |
downloadUpdate(info?) | Download |
switchVersion(info?) | Switch to the downloaded version now (JS reload) |
switchVersionLater(info?) | Apply on next launch |
markSuccess() | Confirm the current version as healthy |
restartApp() | Restart the app |
resetToPackagedBundle(options?) | Return to the bundled JS |
downloadAndInstallApk(url) | Download and install a native upgrade APK (expired package) |
parseTestQrCode(code) | Parse a test QR code / deep link |
dismissError() | Clear lastError |
CheckResult and version info
interface CheckResult {
upToDate?: boolean; // already latest
update?: boolean; // update available
expired?: boolean; // native package expired; downloadUrl points to the new binary
paused?: 'app' | 'package'; // application or native package paused
downloadUrl?: string; // expired-binary download address
bundleStatus?: 'matched' | 'rebuiltSameJs' | 'unknownBundle';
name?: string; // version name
hash?: string; // version hash
description?: string; // version description
metaInfo?: string; // custom metadata (JSON string)
config?: { rollout?: Record<string, number>; forceBoot?: boolean };
pdiff?: string; // precise differential package
diff?: string; // generic differential package
full?: string; // full package
}bundleStatus reflects native registration: matched — full match; rebuiltSameJs — same JS fingerprint but a different build time (full package only); unknownBundle — unregistered fingerprint (kept on the current version under strict channel delivery).
Metadata and crash correlation
import * as Sentry from '@sentry/react-native';
import { attachToSentry, getUpdateMetadata } from 'rn-update';
// Call after your existing Sentry initialization.
attachToSentry(Sentry);
const metadata = getUpdateMetadata();getUpdateMetadata() returns the current update identity (including currentVersion); updateMetadataTags() builds key/value pairs ready for Sentry tags.
Errors and events
UpdateErrorcarries a stable machine-readablecode(UpdateErrorCode).EventData(theloggercallback) includestype(checking,downloading,downloadSuccess,rollback,markSuccess,errorUpdate, …) with error details.For JS error reporting and stack symbolication see Error monitoring.
Pass an initialized reporter with setAttribute/setAttributes to attachToCrashlytics(reporter). The default tag prefix is pakta. and the running update tag is pakta.currentVersion.
| Additional option | Default | Purpose |
|---|---|---|
disableNativeCheck | false | Disable native startup checks |
dismissErrorAfter | unset | Clear lastError after this many milliseconds |
overridePackageVersion | native version | Diagnostic JS request override; does not alter the installer |
Production defaults to alertUpdateAndIgnoreError; development defaults to alwaysAlert. debug enables checks/downloads in development, not actual activation. updateStrategy also accepts null, but manual Provider calls can still prompt; use the instance methods below for fully custom UI.
checkUpdate(params?)
Call inside an UpdateProvider descendant. With no arguments, checks updates for this device, stores updateInfo and runs the configured prompt/download strategy. extra.toHash selects an update for testing; it does not set the native channel. Returns CheckResult or undefined when skipped. Failures go to lastError by default, or throw with throwError enabled. For a raw result and your own UI, use client.checkUpdate() as shown in the manual example.
checkUpdate(params?: { extra?: { toHash?: string } }): Promise<CheckResult | undefined>const { checkUpdate, lastError } = useUpdate();
async function onCheck() {
const info = await checkUpdate();
if (!info) return;
if (info.expired) {
return;
}
if (info.paused) return;
if (info.upToDate) return;
if (info.update) {
}
}downloadUpdate(info?)
Uses the latest check result when info is omitted. Returns true after the Provider download flow; false for no usable update or an afterDownloadUpdate veto, even if files already downloaded. It also runs the activation strategy: silentAndNow requests reload, silentAndLater schedules activation, other values can show a prompt. For download only, client.downloadUpdate(info, onProgress?) returns a hash or undefined; client switching methods accept that hash.
downloadUpdate(info?: CheckResult): Promise<boolean | undefined>const { updateInfo, downloadUpdate } = useUpdate();
async function onDownload() {
if (!updateInfo?.update) return;
const completed = await downloadUpdate(updateInfo);
if (!completed) return;
}downloadAndInstallApk(url)
Downloads a complete Android APK and opens the system installer. The URL must use HTTPS and point to an APK, not an AAB, ppk or store page. Non-Android platforms skip this operation. The APK must match the installed application ID and signing identity and satisfy system version requirements. Promise<void> completion does not prove the user installed the app. Default errors appear in lastError; enable throwError for try/catch.
Add REQUEST_INSTALL_PACKAGES inside manifest, outside application, and rebuild the native installer. The SDK uses Android installation sessions; do not add a FileProvider for this API. Plain HTTP URLs are rejected. The button example below belongs under UpdateProvider and receives the real APK URL, optionally from CheckResult.downloadUrl.
On Android 8+, the user must allow this app to install unknown apps. The SDK opens settings when possible and reports APK_INSTALL_PERMISSION_REQUIRED; after granting permission, return and press the button again. Concurrent downloads are skipped. APK_INSTALL_PENDING means the downloaded APK awaits installation; do not loop downloads. For installation failures check the APK, package ID, signature and version. If distribution requires a store upgrade, use your app’s store link instead.
downloadAndInstallApk(url: string): Promise<void><uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />import { useState } from 'react';
import { Button, Platform, Text, View } from 'react-native';
import { useUpdate, useUpdateProgress } from 'rn-update';
export function NativeUpgradeButton({ apkUrl }: { apkUrl: string }) {
const { downloadAndInstallApk, lastError } = useUpdate();
const progress = useUpdateProgress();
const [busy, setBusy] = useState(false);
const [error, setError] = useState('');
async function install() {
if (busy || !apkUrl) return;
setBusy(true);
setError('');
try {
await downloadAndInstallApk(apkUrl);
} catch (cause) {
setError(cause instanceof Error ? cause.message : String(cause));
} finally {
setBusy(false);
}
}
if (Platform.OS !== 'android') return null;
const percent = progress?.hash === 'downloadingApk' && progress.total > 0
? Math.round(progress.received / progress.total * 100)
: undefined;
return (
<View>
<Button title={busy ? 'Downloading' : 'Upgrade app'}
disabled={busy || !apkUrl} onPress={() => { void install(); }} />
{percent !== undefined ? <Text>{percent}%</Text> : null}
{error || lastError ? <Text>{error || lastError?.message}</Text> : null}
</View>
);
}markSuccess()
Confirms that the running update is usable. Returns true when native code accepts, false when rejected, or undefined when already marked, in development or outside the first update launch. Native failures throw. The Provider normally confirms after about 1000 ms. For late initialization set autoMarkSuccess:false, then call after critical initialization succeeds. Do not mark success immediately after download. Errors occurring after confirmation do not necessarily trigger rollback.
markSuccess(): Promise<boolean | undefined>autoMarkSuccess: false,const { markSuccess } = useUpdate();
async function confirmReady() {
try {
const accepted = await markSuccess();
if (accepted === false) {
}
} catch (error) {
}
}currentVersionInfo
Contains name, description and the JSON-string metaInfo of the running update, or null. updateInfo describes the candidate from the latest check, not the currently running update. currentHash is empty for the embedded bundle; packageVersion is the native installer version and does not change with an update name.
currentVersionInfo: {
name?: string;
description?: string;
metaInfo?: string;
} | nullconst { currentVersionInfo, currentHash, packageVersion } = useUpdate();
const label = currentVersionInfo?.name || 'Embedded version';getCurrentVersionInfo()
Compatibility method returning a Promise of name, description and metaInfo. New code should read currentVersionInfo directly.
getCurrentVersionInfo(): Promise<{
name?: string;
description?: string;
metaInfo?: string;
}>const { getCurrentVersionInfo } = useUpdate();
const version = await getCurrentVersionInfo();restartApp()
Requests a native restart of the React Native environment. It neither checks nor downloads an update and does not promise an OS-level process kill. Save pending work first. beforeReload receives type restartApp; false cancels. Hook and native restart errors reject and should be caught in button handlers.
restartApp(): Promise<void>const { restartApp } = useUpdate();
await restartApp();resetToPackagedBundle(options?)
Removes downloaded updates and local update state, preserving the device ID. It restores the bundle embedded in the installer, not an arbitrary historical update. By default activation waits for the next launch; restart:true additionally requests restart. A true result proves reset, not successful restart: a hook can veto or restarting can fail. Web returns false; unsupported native builds report RESET_FAILED. Check the result. Stop the faulty server release first or a later check can download it again. See stop release.
resetToPackagedBundle(options?: { restart?: boolean }): Promise<boolean | undefined>const { resetToPackagedBundle } = useUpdate();
const reset = await resetToPackagedBundle({ restart: true });
if (!reset) {
}switchVersion(info?)
Immediately switches to an already downloaded update. Defaults to the latest CheckResult, skips when no hash exists, and resolves true when native reload is requested, not when the next launch proves healthy. Download first. beforeReload can cancel with false. The client-instance equivalent accepts a string: client.switchVersion(hash).
switchVersion(info?: CheckResult): Promise<boolean | undefined>const { switchVersion, updateInfo } = useUpdate();
if (updateInfo?.hash) await switchVersion(updateInfo);switchVersionLater(info?)
Schedules an already downloaded update for the next launch, preserving the current screen. Defaults to the latest result; missing hash is skipped. Returns Promise<void> and does not invoke beforeReload. Fully close and reopen to test. The client-instance equivalent is client.switchVersionLater(hash).
switchVersionLater(info?: CheckResult): Promise<void>const { switchVersionLater, updateInfo } = useUpdate();
if (updateInfo?.hash) await switchVersionLater(updateInfo);parseTestQrCode(code)
Accepts a scanned JSON string or UpdateTestPayload object. A true result only means the test payload was recognized, not that download or activation succeeded. Set type to __rnPaktaVersionHash and data to the full update hash. testChannel:false rejects testing payloads. Supply your own scanner UI. For an existing app deep link, append ?type=__rnPaktaVersionHash&data=HASH; the native scheme must already be configured and rebuilt. This differs from the installer’s fixed distribution channel.
parseTestQrCode(code: string | UpdateTestPayload): booleanconst { parseTestQrCode } = useUpdate();
const accepted = parseTestQrCode({
type: '__rnPaktaVersionHash',
data: 'REPLACE_WITH_FULL_UPDATE_HASH',
});useUpdateProgress()
Returns ProgressData or undefined. received and total count bytes; progress is an optional percentage from 0 to 100. APK progress may supply only byte counts. Show an indeterminate state for an unknown total. Use this hook for progress-only components.
import { Text } from 'react-native';
import { useUpdateProgress } from 'rn-update';
export function DownloadProgress() {
const data = useUpdateProgress();
if (!data) return null;
const percent = data.progress ?? (data.total > 0
? Math.round(data.received / data.total * 100) : undefined);
return <Text>{percent === undefined ? 'Downloading' : `${percent}%`}</Text>;
}dismissError()
Clears lastError without retrying or modifying downloaded content. Call when dismissing your error UI. dismissErrorAfter:5000 in client options clears it after five seconds.
const { lastError, dismissError } = useUpdate();Build a custom update UI
Use instance methods when your UI owns the complete flow. client.downloadUpdate returns a hash, and client switching methods accept a hash; these differ from Hook methods. Add checkStrategy:null and throwError:true to the existing client. Native background checks are separate; disableNativeCheck:true disables them and gives up that recovery path. The example downloads and schedules activation for the next launch, reporting progress and errors.
import { useState } from 'react';
import { Button, Text, View } from 'react-native';
import { useUpdate } from 'rn-update';
export function ManualUpdateButton() {
const { client } = useUpdate();
const [busy, setBusy] = useState(false);
const [message, setMessage] = useState('');
async function update() {
if (!client || busy) return;
setBusy(true);
try {
const info = await client.checkUpdate();
if (!info?.update) {
setMessage(info?.expired ? '请Upgrade app' : 'No available update');
return;
}
const hash = await client.downloadUpdate(info, (data) => {
setMessage(data.progress === undefined ? 'Downloading' : `${data.progress}%`);
});
if (!hash) return;
await client.switchVersionLater(hash);
setMessage('Downloaded; applies on next launch');
} catch (error) {
setMessage(error instanceof Error ? error.message : String(error));
} finally {
setBusy(false);
}
}
return <View>
<Button title="Check and download" disabled={busy} onPress={() => { void update(); }} />
<Text>{message}</Text>
</View>;
}Check, download and reload hooks
Add hooks to the existing client. beforeCheckUpdate returning false skips checking. afterCheckUpdate receives completed/skipped/error plus result or error and does not replace the result. beforeDownloadUpdate returning false skips download. afterDownloadUpdate returning false stops Provider post-download actions. onPackageExpired returning false prevents built-in installer-upgrade handling. beforeReload receives type switchVersion/restartApp and optional hash; false or a thrown error prevents reload.
The example calls your own savePendingDrafts function, which returns whether it is safe to continue. Bound asynchronous cleanup so the update UI does not wait indefinitely.
beforeReload: async ({ type }) => {
if (type === 'switchVersion') {
const saved = await savePendingDrafts();
return saved;
}
return true;
},Native startup checks
disableNativeCheck defaults to false: native checks run independently after cold starts and can download repairs when JavaScript is unavailable. checkStrategy:null does not turn off that network request. A server forceBoot directive can schedule repair activation for a later launch; local rollback protection still applies. See brick rescue.
captureException(error, context?)
Use the existing client to report caught JavaScript errors. Uncaught errors are reported automatically. disableErrorReporting disables error reporting specifically; disableTelemetry also blocks the related transport. Include only useful diagnostic context. Archive the matching sourcemap and follow error diagnosis.
const { client } = useUpdate();
try {
await submitOrder();
} catch (error) {
client?.captureException(error, { context: 'checkout' });
}Android mixed apps: setCustomInstanceManager
For an Android host that owns a ReactInstanceManager instead of a standard ReactApplication, register the same live instance after creating it. This only supplies the reload target. The instance still needs UpdateContext.getBundleUrl(context) as its bundle path. Standard RN apps should follow native integration without creating an additional instance.
import cn.reactnative.modules.update.UpdateContext;
UpdateContext.setCustomInstanceManager(reactInstanceManager);