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

@codeonair/code-push-react-native

v1.1.1

Published

CodePush SDK for React Native: over-the-air (OTA) JavaScript and asset updates with mandatory releases, staged rollouts and crash rollback. App Center CodePush alternative.

Readme

@codeonair/code-push-react-native

The CodePush SDK for React Native: over-the-air (OTA) JavaScript and asset updates from CodeOnAir CodePush, with mandatory releases, staged rollouts and automatic rollback of an update that crashes. An alternative to App Center CodePush and react-native-code-push. Works with the Old Architecture, the New Architecture (including bridgeless) and Hermes, on React Native 0.70+.

Website · Quick start · Release updates with the CLI: @codeonair/code-push-cli

| Tested on devices (Android emulator + iOS simulator) | Old Architecture | New Architecture | | --- | --- | --- | | React Native 0.86 | — (removed in RN 0.82) | ✅ | | React Native 0.76 | ✅ | ✅ |

Each run covers: optional update on the next start, mandatory update right away, and rollback of an update that crashes at startup.

npm install @codeonair/code-push-react-native
cd ios && pod install

Configure

Dashboard → your app → CodePush → Android / iOS → Set up CodePush. Use your platform's deployment key and the server URL:

<!-- android/app/src/main/res/values/strings.xml -->
<string moduleConfig="true" name="CodePushDeploymentKey">cpd_…</string>
<string moduleConfig="true" name="CodePushServerUrl">https://app.codeonair.com</string>
<!-- ios/<App>/Info.plist -->
<key>CodePushDeploymentKey</key>
<string>cpd_…</string>
<key>CodePushServerURL</key>
<string>https://app.codeonair.com</string>

Load the update's bundle

// MainApplication.kt
import com.codeonair.codepush.CodeOnAirCodePush

getDefaultReactHost(
  context = applicationContext,
  packageList = PackageList(this).packages,
  jsBundleFilePath = CodeOnAirCodePush.getJSBundleFile(applicationContext),
)

React Native 0.70–0.76 (DefaultReactNativeHost in MainApplication) — the same override works for the Old and the New Architecture:

// MainApplication.kt
import com.codeonair.codepush.CodeOnAirCodePush

override val reactNativeHost: ReactNativeHost =
    object : DefaultReactNativeHost(this) {
      // …getPackages(), getJSMainModuleName() as before…
      override fun getJSBundleFile(): String? = CodeOnAirCodePush.getJSBundleFile(applicationContext)
    }
// AppDelegate.swift
import CodeOnAirCodePush

override func bundleURL() -> URL? {
#if DEBUG
  RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index")
#else
  CodeOnAirCodePush.bundleURL()
#endif
}

React Native 0.70–0.76 (AppDelegate.mm), Old and New Architecture:

#import <CodeOnAirCodePush/CodeOnAirCodePush.h>

- (NSURL *)bundleURL
{
#if DEBUG
  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
#else
  return [CodeOnAirCodePush bundleURL];
#endif
}

Notes:

  • React Native 0.76 and older with Xcode 16.3+ fail to compile the fmt pod (call to consteval function … is not a constant expression). That's React Native, not CodePush: upgrade React Native, or turn off fmt's consteval in your Podfile's post_install (replace define FMT_USE_CONSTEVAL 1 with 0 in Pods/fmt/include/fmt/base.h).
  • iOS 27 stops apps that haven't adopted the UIScene lifecycle at launch; the stock React Native template hasn't yet.

Use

import CodePush from "@codeonair/code-push-react-native";

function App() {
  useEffect(() => {
    // Every launch: confirms the running update, then checks for a new one.
    CodePush.sync(
      {
        installMode: CodePush.InstallMode.ON_NEXT_RESTART, // optional updates: on the next app start
        mandatoryInstallMode: CodePush.InstallMode.IMMEDIATE, // Mandatory builds: right away
      },
      (status) => {
        if (status === CodePush.SyncStatus.UPDATE_INSTALLED) console.log("Update installed.");
      },
    );
  }, []);
  // …
}

export default App;

Call CodePush.sync() on every launch: it confirms the running update first, so an update that crashes before then is rolled back on the next launch and reported. installMode applies to optional updates (default ON_NEXT_RESTART) and mandatoryInstallMode to builds marked Mandatory (default IMMEDIATE); either can be any mode:

| Install mode | When the update runs | | --- | --- | | ON_NEXT_RESTART | The next time the app is started. | | IMMEDIATE | Right away: the app restarts as soon as it's downloaded. | | ON_NEXT_RESUME | When the app next comes back from the background. | | ON_NEXT_SUSPEND | While the app is in the background — the user comes back to the new version already running. |

minimumBackgroundDuration (seconds, default 0) makes ON_NEXT_RESUME / ON_NEXT_SUSPEND wait until the app has been in the background at least that long, so a quick app switch doesn't restart it.

Mandatory updates without a visible reload

The old setup keeps working exactly as before. To never restart in front of the user, install mandatory updates with ON_NEXT_SUSPEND and bring them back to the same screen:

import codePush from "@codeonair/code-push-react-native";
import { NavigationContainer } from "@react-navigation/native";

function App() {
  return (
    <NavigationContainer
      initialState={codePush.restoredScreenState} // the screen from before a CodePush restart, else undefined
      onStateChange={codePush.trackScreenState}>
      {/* … */}
    </NavigationContainer>
  );
}

export default codePush({
  mandatoryInstallMode: codePush.InstallMode.ON_NEXT_SUSPEND,
  minimumBackgroundDuration: 10,
  restoreScreen: true, // loads the saved screen state before the app renders
})(App);

Any other state, or without the wrapper: codePush.setRestartStateProvider(() => state) is called just before every CodePush restart (any JSON), and await codePush.getRestoredState() returns it once after the restart. It's null after a normal cold start and when the update rolled back. React Navigation isn't a dependency.

How ON_NEXT_SUSPEND restarts: about a second after the app goes to the background (or after minimumBackgroundDuration), a native timer restarts it — iOS reloads React Native under a background task; Android points the ReactHost (or ReactInstanceManager) at the new bundle and reloads it in place, or ends the process if that isn't possible so the next start runs the update. Coming back first cancels it until the next time the app is in the background. iOS gives a backgrounded app about 30 seconds and Android may freeze it sooner, so keep the wait short; the update always runs on the next cold start anyway.

export default codePush(App) is an optional wrapper that syncs on start. checkForUpdate(), install(), notifyAppReady(), restartApp() and getUpdateMetadata() are there for custom flows.

Release updates with the CLI, @codeonair/code-push-cli (npm install -g @codeonair/code-push-cli@beta). Full docs: dashboard.codeonair.com/docs/codepush/overview.

The JavaScript engine (src/core.ts) is tested end to end against the CodeOnAir API, including install modes, restart state and rollback.