npm package: @rootpush/updates
Description: OTA updates in React Native, with rollback support
Author: RootPush
Latest version: 0.3.7

# @rootpush/updates

A lightweight Over-The-Air (OTA) update solution for React Native applications with built-in rollback support. This library allows you to deliver bundle updates to your React Native app without going through the app store review process.

## Features

- Supports bridgeless and new arch.
- Supports branches for QA or internal testing.
- Built-in rollback support
- TypeScript support
- CLI tool for easy deployments

## Getting Started

1. Create your account at [https://rootpush.com](https://rootpush.com)
2. Create an application in the dashboard
3. Create a deployment key for your application

## Automatic Installation

Install the CLI.

See usage examples at: https://github.com/rootpush/cli?tab=readme-ov-file#usage

```sh
npm i -g @rootpush/cli
```

This will install the @rootpush/updates package, configure your iOS and Android files and install the pod.

```sh
rootpush install --product updates
```

You can check all the changes with git. If you have a custom setup, installation can fail.
```sh
git diff
```

## Add configuration to your App.jsx/tsx

```typescript
...
import Updates from '@rootpush/updates';
...

export default function App() {
  const key =
    Platform.select({
      ios: 'a69f3fa0-9109-44a2-8e2b-bb9e69f58f41',
      android: '5a8607dd-b19e-4b01-b365-6b915fb3a326',
    }) ?? '';
  const branch = 'master';

  React.useEffect(() => {
    ReactNativeUpdates.sync(key, branch);
  // useEffect will allow you to programmatically change the branch
  }, [key, branch]);

  return (
    ...
  )
}
```

More examples here: https://github.com/rootpush/updates/blob/main/example/src/App.tsx

## Manual Installation Expo

```sh
npm install @rootpush/updates @rootpush/updates-expo-plugin
```

Add the plugin to your app.json or app.config.js:

```json
{
  "expo": {
    "plugins": [
      "@rootpush/updates-expo-plugin"
    ]
  }
}
```

## Manual Installation Bare Project

Install the updates package.

```sh
npm install @rootpush/updates
```

### Android

You'll need to modify your main application file.

**In your app:**
Located at `android/app/src/main/java/com/your-app-name/MainApplication.kt` (or .java if using Java)

**Example implementation:**
See the [example implementation](example/android/app/src/main/java/rootpush/updates/example/MainApplication.kt) in our repo.

Add the following import and override the `getJSBundleFile()` method:

1. Add the import at the top of the file:

```kotlin
package ...

+ import com.rootpush.updates.UpdatesPreferences
```

2. Add getJSBundleFile to the class:

```kotlin
+ override fun getJSBundleFile(): String {
+     return UpdatesPreferences(this.application.applicationContext).getFullBundlePath()
+ }
```

### iOS

You'll need to modify your app delegate file.

**In your app:**
Located at `ios/YourAppName/AppDelegate.mm` (or .swift if using Swift)

**Example implementation:**
See the [example implementation](example/ios/UpdatesExample/AppDelegate.mm) in our repo.

Make the following changes:

1. Add the import at the top of the file:

Objective-C++
```objectivec
+ #import "UpdatesPreferences.h"
```
Swift
```swift
...
+ import RootPushUpdates
...
```

2. Replace the existing bundle URL code with:

Objective-C++
```objectivec
#if DEBUG
  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
#else
+  UpdatesPreferences *preferences = [[UpdatesPreferences alloc] init];
+  return [NSURL fileURLWithPath:[preferences getFullBundlePath]];
#endif
```
Swift
```swift
#if DEBUG
  return RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index")
#else
+  let preferences = UpdatesPreferences()
+  return URL(fileURLWithPath: preferences.getFullBundlePath())
#endif
```

### Advanced Usage

For more control over the update process, you can use the individual methods:

```javascript
import Updates from '@rootpush/updates';

// Configure the update service
Updates.setConfiguration(
  'YOUR_DEPLOYMENT_KEY',
  'production', // or your branch name
);

// Check for updates
try {
  await Updates.check();

  // Check if update was downloaded and is ready to install
  if (Updates.hasPendingUpdate()) {
    // Install the update and reload the app
    await Updates.install();
  }
} catch (error) {
  console.error('Update process failed:', error);
}
```

## Deploying Updates

To deploy updates to your app, use the `@rootpush/cli` tool. Here's how to get started:

https://github.com/rootpush/cli?tab=readme-ov-file#usage

The CLI tool automatically detects your project type (Expo or bare React Native), branch, and target version, using the appropriate bundling commands for your setup.

## API Reference

### `setConfiguration(key: string, branch: string)`

Sets up the configuration for the update service.

- `key`: Your deployment key
- `branch`: The branch to use for updates (e.g., 'production', 'staging')

### `check(): Promise<void>`

Checks for available updates and downloads them if available.

### `install(): Promise<void>`

Installs a previously downloaded update and reloads the app.

### `rollback(): Promise<void>`

Roll back to a previous bundle. The system does this automatically if issues occur after installation, or you can trigger it manually.

### `hasPendingUpdate(): boolean`

Checks if there is a pending update ready to install.

### `sync(key: string, branch: string): Promise<void>`

Convenience method that combines configuration, checking, and installation of updates. This method will:

1. Set the configuration with the provided parameters
2. Check for updates
3. If an update is pending, install it

## Development Mode

All update functions are automatically disabled in development mode (`__DEV__`). When in development mode:

- `check()` will return immediately
- `install()` will return immediately
- `rollback()` will return immediately
- Other functions like `hasPendingUpdate()` and `setConfiguration()` will still work normally

## Contributing

See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow.

## License

MIT