Methods
The SDK exposes two imperative surfaces:
Swiftpatch— a tree-shakable namespace facade. Use this for event subscriptions and orchestrator verbs from anywhere in your app.SwiftPatch— a class for environments with no React provider (headless JS, background tasks, native callbacks).
Most apps should stick with Swiftpatch plus hooks + provider. The SwiftPatch class is for advanced use cases.
The Swiftpatch facade
import { Swiftpatch } from '@swiftpatch/react-native';
Event subscriptions
Every Swiftpatch.on*() call returns an unsubscribe function. Safe to call before the provider mounts — subscriptions are remembered.
const unsub1 = Swiftpatch.onUpdateAvailable((update) => {
console.log('Check found:', update.version);
});
const unsub2 = Swiftpatch.onUpdateReady((update) => {
console.log('Downloaded + ready:', update.version);
});
const unsub3 = Swiftpatch.onUpdateApplied((update) => {
console.log('Running the new bundle:', update.version);
});
const unsub4 = Swiftpatch.onUpdateDismissed((update) => {
console.log('User tapped Later on:', update.version);
});
const unsub5 = Swiftpatch.onError((error) => {
console.warn('Swiftpatch error:', error.code, error.message);
});
const unsub6 = Swiftpatch.onProgress(({ loaded, total }) => {
console.log(`${loaded} / ${total} bytes`);
});
const unsub7 = Swiftpatch.onRollback((reason) => {
console.warn('Rolled back:', reason);
});
// Wildcard — every event type
const unsub8 = Swiftpatch.on('*', (event) => {
console.log(event.type, event);
});
See Events for the full list of event types and payloads.
Orchestrator verbs
Once the provider is mounted (or new SwiftPatch().init() has completed), these are safe to call from anywhere.
// Apply the ready update + restart
await Swiftpatch.applyNow();
// Persist a per-release dismissal. A newer release will still surface.
await Swiftpatch.dismissUpdate();
// Snapshot of the current lifecycle state
const state = await Swiftpatch.getCurrentState();
// { phase: 'idle' | 'checking' | 'downloading' | 'ready' | 'applying' | 'error',
// current: BundleInfo | null,
// pending: UpdateInfo | null,
// lastCheckedAt: Date | null,
// lastError: SwiftPatchError | null }
// Persist a user-facing policy
await Swiftpatch.setUpdatePolicy({
prompt: 'mandatory-only', // 'always' | 'mandatory-only' | 'silent'
applyTiming: 'on-resume', // 'immediate' | 'on-resume' | 'on-next-launch'
});
const policy = await Swiftpatch.getUpdatePolicy();
// After a failed apply, retry once
await Swiftpatch.retryFailedUpdate();
// Check whether a given release should prompt (honors policy + dismissals)
const should = await Swiftpatch.shouldPromptFor(release);
// Check whether a release was previously dismissed
const dismissed = await Swiftpatch.isReleaseDismissed(release);
Channels
Channels let you ship to a subset of users (for example, beta) before promoting globally.
import { setChannel, getChannel, onChannelChanged } from '@swiftpatch/react-native';
// Set the active channel — persists to native storage.
await setChannel('beta');
// Read the current channel (hydrates from native on first call)
const current = await getChannel(); // 'production' | 'beta' | ...
// Subscribe to changes
const unsub = onChannelChanged((channel) => {
console.log('Channel is now:', channel);
});
Every checkForUpdate call passes the channel. Default is production. Custom channel names are allowed — configure them in the dashboard. See Channels guide.
Custom breadcrumbs
Forward Swiftpatch lifecycle events to your crash-reporting tool.
import { SwiftPatch } from '@swiftpatch/react-native';
const sp = new SwiftPatch({ deploymentKey: 'dep_xxx' });
await sp.init();
const unsub = sp.addBreadcrumbSink((crumb) => {
myTelemetry.log(crumb.message, {
level: crumb.level,
category: crumb.category,
data: crumb.data,
});
});
// Or emit your own crumb
sp.breadcrumb('info', 'user_tapped_apply', { releaseId: 'r_abc' });
One-liner adapters are shipped for the three popular vendors. See Integrations:
import { installSentrySink } from '@swiftpatch/react-native/integrations/sentry';
import * as Sentry from '@sentry/react-native';
installSentrySink(Sentry);
White-label — runtime tenant switching
Use one binary for many brands. Rotate the deployment key at runtime without restarting.
const sp = new SwiftPatch({ deploymentKey: initialKey });
await sp.init();
// Soft switch: next checkForUpdate uses the new tenant's release line.
await sp.setDeploymentKey(tenantKey);
// Hard switch: roll back to the store bundle and wipe all slots, so the user
// boots clean on the new tenant.
await sp.setDeploymentKey(tenantKey, { clearCurrentBundle: true });
// Read the persisted key
const key = sp.getDeploymentKey();
// Subscribe to changes — for example, re-theme the app after auth.
sp.onTenantChanged((key) => console.log('Tenant switched:', key));
See White-label guide.
The SwiftPatch class — non-React usage
For headless JS, background tasks, or native callbacks, construct a SwiftPatch instance directly:
import { SwiftPatch } from '@swiftpatch/react-native';
const sp = new SwiftPatch({
deploymentKey: 'dep_xxx',
debug: __DEV__,
});
await sp.init();
// Check
const release = await sp.checkForUpdate();
if (release) {
// Download (uses delta-patch pipeline automatically when a patch is offered)
await sp.download(release);
// Install
await sp.install(release);
// Or do both in one call
// await sp.downloadAndInstall(release);
// Restart
sp.restart(release.id);
}
// Channels
await sp.setChannel('beta');
const channel = await sp.getChannel();
// Rollback to the previous bundle
await sp.rollback();
// Bundle info
const bundle = await sp.getCurrentBundle();
// Test the backend connection (no init required)
const ping = await sp.testConnection();
// { connected: true, app: {...}, organization: {...} }
Static helpers
import {
SwiftPatch,
getKnownErrors,
getErrorDescription,
testConnection,
getNativeConfig,
restart,
} from '@swiftpatch/react-native';
// Static — no init, no native call. Safe to call at module load.
const codes = SwiftPatch.getKnownErrors();
// ['SWIFTPATCH_DOWNLOAD_FAILED', 'SWIFTPATCH_HASH_MISMATCH', ...]
// Human-readable error copy
const info = getErrorDescription('SWIFTPATCH_SIGNATURE_INVALID');
// Quick connection check without full SDK init
const ping = await testConnection({ deploymentKey: 'dep_xxx' });
// Read native config
const cfg = await getNativeConfig();
// Force a JS reload (rarely needed — use applyNow instead)
restart();
Next steps
- Events — what fires when.
- Types — the full type surface.
- Error codes — the 33-code taxonomy.
- Integrations — Sentry, Bugsnag, Crashlytics.