npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@upfluxhq/capacitor

v1.0.1

Published

Capacitor SDK for Upflux OTA updates

Downloads

314

Readme

@upfluxhq/capacitor

Capacitor SDK for Upflux OTA updates.

Installation

npm install @upfluxhq/capacitor
# or
yarn add @upfluxhq/capacitor
# or
pnpm add @upfluxhq/capacitor

Setup

No additional native setup required! The SDK uses Capacitor's built-in WebView APIs.

Just sync your Capacitor project after installing:

npx cap sync

Usage

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 android

The CLI will:

  1. Detect capacitor.config.json/ts/js
  2. Read the webDir setting (default: www)
  3. Zip the web directory
  4. 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

  1. Check: App calls /updates/check with device info
  2. Download: If update available, downloads zip bundle
  3. Extract: Bundle is extracted using JSZip
  4. Apply: WebView.setServerBasePath() points to new bundle
  5. Persist: WebView.persistServerBasePath() survives restarts
  6. 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