@upfluxhq/capacitor
v1.0.1
Published
Capacitor SDK for Upflux OTA updates
Downloads
314
Maintainers
Readme
@upfluxhq/capacitor
Capacitor SDK for Upflux OTA updates.
Installation
npm install @upfluxhq/capacitor
# or
yarn add @upfluxhq/capacitor
# or
pnpm add @upfluxhq/capacitorSetup
No additional native setup required! The SDK uses Capacitor's built-in WebView APIs.
Just sync your Capacitor project after installing:
npx cap syncUsage
Basic Setup
import { Upflux } from '@upfluxhq/capacitor';
// Configure the SDK
const upflux = new Upflux({
appId: 'your-app-id',
deployment: 'production',
clientKey: 'your-client-key',
serverUrl: 'https://your-api-server.com'
});
// Initialize on app startup
await upflux.init();Check for Updates
const updateInfo = await upflux.checkForUpdates();
if (updateInfo.updateAvailable) {
console.log('Update available:', updateInfo.releaseLabel);
}Download and Apply Update
if (updateInfo.updateAvailable) {
// Download the update
const downloadResult = await upflux.downloadUpdate(updateInfo, {
onProgress: (progress) => {
console.log(`Download progress: ${progress.percentage}%`);
}
});
if (downloadResult.success) {
// Apply and reload
await upflux.applyUpdate(downloadResult);
// App will reload here
}
}Complete Example
import { Upflux } from '@upfluxhq/capacitor';
const upflux = new Upflux({
appId: 'my-app',
deployment: 'production',
clientKey: 'your-client-key',
serverUrl: 'http://localhost:4000'
});
async function initApp() {
// Initialize SDK
const startupBundle = await upflux.init();
if (startupBundle.isUpdate) {
console.log('Running OTA version:', startupBundle.releaseLabel);
}
}
async function checkForUpdates() {
try {
const updateInfo = await upflux.checkForUpdates();
if (updateInfo.updateAvailable) {
if (confirm(`Update ${updateInfo.releaseLabel} available. Install now?`)) {
await installUpdate(updateInfo);
}
} else {
console.log('App is up to date');
}
} catch (error) {
console.error('Error checking for updates:', error);
}
}
async function installUpdate(updateInfo) {
try {
const downloadResult = await upflux.downloadUpdate(updateInfo);
if (downloadResult.success) {
await upflux.applyUpdate(downloadResult);
// App will reload
}
} catch (error) {
console.error('Error installing update:', error);
}
}
// Initialize on page load
initApp();API Reference
Upflux Class
constructor(config: UpfluxConfig)
Create a new Upflux instance.
interface UpfluxConfig {
appId: string; // Your app identifier
deployment: string; // Deployment name (e.g., 'production', 'staging')
clientKey: string; // Client key from dashboard
serverUrl: string; // Upflux API server URL
}init(): Promise<StartupBundle>
Initialize the SDK. Call this early in app startup.
checkForUpdates(deviceInfo?: Partial<DeviceInfo>): Promise<UpdateInfo>
Check if an update is available.
downloadUpdate(info: UpdateInfo, options?: DownloadOptions): Promise<DownloadResult>
Download an available update.
applyUpdate(result: DownloadResult): Promise<ApplyResult>
Apply a downloaded update and reload the app.
clearUpdate(): Promise<void>
Clear the current update and revert to default bundle on next reload.
isInitialized(): boolean
Check if the SDK has been initialized.
getStartupBundle(): StartupBundle | null
Get the startup bundle info from init().
getConfig(): UpfluxConfig
Get the current SDK configuration.
destroy(): void
Destroy the SDK instance and clean up resources.
Store Update Required
When a release is published with --min-binary-version, devices with a lower binary version receive storeUpdateRequired: true instead of an OTA bundle:
const updateInfo = await upflux.checkForUpdates();
if (updateInfo.storeUpdateRequired) {
// Direct users to the app store
const storeUrl = platform === 'ios'
? 'https://apps.apple.com/app/my-app'
: 'https://play.google.com/store/apps/details?id=com.myapp';
// Show your custom UI or open store directly
window.open(storeUrl);
} else if (updateInfo.updateAvailable) {
// Normal OTA flow
const result = await upflux.downloadUpdate(updateInfo);
await upflux.applyUpdate(result);
}Creating Releases
The Upflux CLI auto-detects Capacitor projects and handles bundling:
# Build your app first
npm run build
# Release to Upflux (auto-detects Capacitor and zips www/)
upflux release --label v1.0.0 --platform androidThe CLI will:
- Detect
capacitor.config.json/ts/js - Read the
webDirsetting (default:www) - Zip the web directory
- Upload to Upflux
Storage Location
Updates are stored in the app's data directory:
<DataDirectory>/upflux/
├── activeBundle.json # Currently active release info
├── deviceId.txt # Persistent device ID
├── currentPath.txt # Current WebView path
└── v1.0.0/ # Extracted release
├── index.html
├── main.js
└── ...How It Works
- Check: App calls
/updates/checkwith device info - Download: If update available, downloads zip bundle
- Extract: Bundle is extracted using JSZip
- Apply:
WebView.setServerBasePath()points to new bundle - Persist:
WebView.persistServerBasePath()survives restarts - Reload: Page reloads to apply changes
Troubleshooting
Update Not Persisting After Restart
Ensure your Capacitor version is 5.0+ which includes persistServerBasePath().
Bundle Not Loading
Check that your build output includes a valid index.html at the root.
Network Errors
For local development, ensure your server is accessible from the device/emulator.
License
MIT
