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

@viettelpost/react-native-ota

v0.1.10

Published

ViettelPost React Native OTA runtime and deploy CLI

Readme

@viettelpost/react-native-ota

Standalone React Native OTA runtime and deploy CLI.

This package contains:

  • ota deploy: build, zip assets, hash, sign, and register OTA release metadata.
  • JS API: OTA.configure(), OTA.sync(), status helpers, and dev utilities.
  • Native runtime: Android Kotlin and iOS Swift/ObjC++ bundle resolver, installer, verification, rollback, and cleanup.

This package does not integrate itself into a host app. The host app must wire the native bundle resolver at startup before OTA bundles can run. Each host app must provide the appKey generated for its OTA app row so the backend can resolve its bundle ID and channel.

Setup

Install the package and initialize OTA files from the host React Native app root:

yarn add @viettelpost/react-native-ota
yarn ota init

The initializer creates missing ota.config.js and .env.ota files, adds .env.ota to .gitignore, and never overwrites existing files. Fill the runtime app identity in .env.ota:

OTA_API=https://stg-f2c-api.viettelpost.vn/vipo-ota
OTA_APP_KEY=

The generated ota.config.js reads these values automatically:

module.exports = {
  api: process.env.OTA_API,
  appKey: process.env.OTA_APP_KEY,
  entryFile: 'index.js',
};

CLI

yarn ota deploy --platform android --dry-run
yarn ota deploy --platform ios --dry-run
yarn ota sign --platform ios --bundle ./build/main.jsbundle --version 2026.06.26-001
yarn ota serve --platform android

Deploys use backend storage by default. The CLI uploads bundle files to vipomall-ota, and the backend stores them through its configured S3 provider. Use --storage external only when registering files already hosted elsewhere. Non-dry-run deployment and release-management commands require OTA_ADMIN_KEY to be injected by the CI secret manager. Do not store that key in .env.ota or bundle it into the mobile app.

JS API

import { OTA } from '@viettelpost/react-native-ota';

OTA.configure({
  appKey: 'apk_...',
  baseURL: 'https://ota.example.com',
});

const result = await OTA.sync();

For automatic install behavior, keep scheduling and UI in the host app:

import {
  checkForUpdate,
  installUpdate,
  reloadApp,
} from '@viettelpost/react-native-ota';

const update = await checkForUpdate('https://ota.example.com', {
  appKey: 'apk_...',
  deviceId: 'stable-installation-id',
});

if (update?.isMandatory) {
  // Show the host app's blocking update dialog.
  await installUpdate(update);
  await reloadApp();
}
  • Mandatory releases should block normal app use, offer an Update now action, and auto-proceed after a short grace period.
  • Non-mandatory releases should remain silent and call installUpdate() only after the app resumes from a sufficiently long background period.
  • reloadApp() reloads the React Native bridge; it does not kill the OS process.
  • Always provide a stable deviceId so the backend can consistently enforce rollout percentages before returning update metadata.
  • OTAConfig.policy is deprecated. Install timing belongs to the host app because the package is intentionally headless.

Security

The client verifies SHA-256 for the bundle and optional assets.zip, then verifies an RSA-SHA256 signature over the canonical metadata payload. The private key must never be committed. Runtime update checks send only X-APP-KEY; they never send X-ADMIN-KEY or require a logged-in user. The app key identifies the app channel and is not a release-management credential.

Example

The package test host lives in example/AwesomeProject and uses React Native 0.77.3. Use it for package-level OTA testing instead of validating package changes through a production host app.