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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@punk_rock_malchik/react-native-sdk

v1.0.1

Published

React Native SDK for OTA Update System - Over-the-air updates for React Native applications

Downloads

16

Readme

@punk_rock_malchik/react-native-sdk

React Native SDK для системы OTA обновлений. Позволяет обновлять JavaScript bundle и ресурсы React Native приложения без перепубликации через App Store/Google Play.

npm version License: MIT

Установка

npm install @punk_rock_malchik/react-native-sdk @react-native-async-storage/async-storage

Дополнительные зависимости

Для работы с файловой системой (выберите один вариант)

Вариант 1: react-native-fs (рекомендуется для bare React Native)

npm install react-native-fs
# Для iOS
cd ios && pod install

Вариант 2: expo-file-system (только для Expo проектов)

npm install expo-file-system

Для вычисления SHA256 checksum (выберите один вариант)

Вариант 1: react-native-crypto (рекомендуется)

npm install react-native-crypto
# Для iOS
cd ios && pod install

Вариант 2: crypto-js (легковесная альтернатива)

npm install crypto-js
npm install --save-dev @types/crypto-js

Вариант 3: expo-crypto (только для Expo проектов)

npm install expo-crypto

Быстрый старт

Базовое использование

import { OTAUpdate } from "@punk_rock_malchik/react-native-sdk";
import { Platform } from "react-native";
import Constants from "expo-constants";

// Инициализация SDK
const ota = new OTAUpdate(
    {
        apiBaseUrl: "http://localhost:3000/api",
        currentVersion: "1.0.0", // Текущая версия bundle
        appVersion: Constants.expoConfig?.version || "1.0.0", // Версия нативного приложения
        platform: Platform.OS === "ios" ? "ios" : "android",
        environment: __DEV__ ? "dev" : "production",
        deviceId: "unique-device-id", // Опционально, для rollout логики
    },
    {
        onCheckComplete: (response) => {
            if (response.available) {
                console.log("Доступно обновление:", response.update?.version);
            }
        },
        onDownloadProgress: (progress) => {
            console.log(`Загрузка: ${Math.round(progress.progress * 100)}%`);
        },
        onInstallComplete: (version) => {
            console.log("Обновление установлено:", version);
            // Перезагрузить приложение для применения обновления
        },
        onError: (error) => {
            console.error("Ошибка OTA:", error);
        },
    }
);

// Проверка и установка обновлений
await ota.checkAndInstall();

Пример интеграции в React компонент

import React, { useEffect, useState } from "react";
import { View, Text, Button, ActivityIndicator } from "react-native";
import { OTAUpdate } from "@punk_rock_malchik/react-native-sdk";

const App: React.FC = () => {
    const [updateStatus, setUpdateStatus] = useState<
        "checking" | "downloading" | "installing" | "idle"
    >("idle");
    const [progress, setProgress] = useState(0);
    const [updateInfo, setUpdateInfo] = useState(null);

    useEffect(() => {
        checkForUpdates();
    }, []);

    const checkForUpdates = async () => {
        try {
            setUpdateStatus("checking");

            const ota = new OTAUpdate(
                {
                    apiBaseUrl: "http://your-api-url/api",
                    currentVersion: "1.0.0",
                    appVersion: "1.0.0",
                    platform: "ios",
                    environment: "production",
                },
                {
                    onDownloadProgress: (p) => {
                        setProgress(p.progress);
                        setUpdateStatus("downloading");
                    },
                    onInstallStart: () => {
                        setUpdateStatus("installing");
                    },
                    onInstallComplete: (version) => {
                        setUpdateStatus("idle");
                        alert(
                            `Обновление ${version} установлено! Перезапустите приложение.`
                        );
                    },
                }
            );

            await ota.checkAndInstall();
        } catch (error) {
            console.error("Ошибка обновления:", error);
            setUpdateStatus("idle");
        }
    };

    return (
        <View>
            {updateStatus === "checking" && <ActivityIndicator />}
            {updateStatus === "downloading" && (
                <View>
                    <Text>
                        Загрузка обновления: {Math.round(progress * 100)}%
                    </Text>
                    <ActivityIndicator />
                </View>
            )}
            {updateStatus === "installing" && (
                <Text>Установка обновления...</Text>
            )}
            <Button title="Проверить обновления" onPress={checkForUpdates} />
        </View>
    );
};

export default App;

API

Класс OTAUpdate

Главный класс для управления обновлениями.

Конструктор

new OTAUpdate(config: OTAConfig, callbacks?: OTACallbacks)

Методы

checkAndInstall(): Promise<CheckUpdateResponse>

Полный цикл: проверка → скачивание → установка.

const response = await ota.checkAndInstall();
if (response.available) {
    console.log("Обновление установлено");
}
checkOnly(): Promise<CheckUpdateResponse>

Только проверка обновлений без скачивания.

const response = await ota.checkOnly();
if (response.available) {
    console.log("Доступно обновление:", response.update?.version);
}
downloadAndInstall(update: UpdateInfo): Promise<void>

Скачивание и установка конкретного обновления.

getCurrentVersion(): Promise<string | null>

Получает текущую установленную версию.

rollback(): Promise<string | null>

Откатывает к предыдущей версии.

Конфигурация (OTAConfig)

interface OTAConfig {
    apiBaseUrl: string; // URL API (например: http://localhost:3000/api)
    currentVersion: string; // Текущая версия bundle
    appVersion: string; // Версия нативного приложения
    platform: "ios" | "android"; // Платформа
    environment: "dev" | "staging" | "production"; // Окружение
    deployment?: string; // Deployment name (опционально)
    deviceId?: string; // Device ID для rollout (опционально)
    timeout?: number; // Таймаут запросов (мс, по умолчанию 10000)
    maxRetries?: number; // Максимум попыток скачивания (по умолчанию 3)
}

Callbacks (OTACallbacks)

interface OTACallbacks {
    onCheckStart?: () => void;
    onCheckComplete?: (response: CheckUpdateResponse) => void;
    onCheckError?: (error: Error) => void;

    onDownloadStart?: () => void;
    onDownloadProgress?: (progress: DownloadProgress) => void;
    onDownloadComplete?: (filePath: string) => void;
    onDownloadError?: (error: Error) => void;

    onInstallStart?: () => void;
    onInstallComplete?: (version: string) => void;
    onInstallError?: (error: Error) => void;
}

Структура SDK

react-native-sdk/
├── src/
│   ├── classes/
│   │   ├── OTAUpdate.ts          # Главный класс
│   │   ├── UpdateChecker.ts      # Проверка обновлений
│   │   ├── BundleDownloader.ts   # Скачивание bundle
│   │   ├── BundleInstaller.ts    # Установка bundle
│   │   └── StatisticsReporter.ts # Статистика
│   ├── types/
│   │   └── index.ts              # TypeScript типы
│   ├── utils/
│   │   ├── http.util.ts          # HTTP утилиты
│   │   └── checksum.util.ts      # Проверка checksum
│   └── index.ts                  # Главный экспорт
├── package.json
└── tsconfig.json

Особенности

  • ✅ Проверка обновлений с кэшированием
  • ✅ Скачивание bundle файлов с прогрессом
  • ✅ Проверка checksum (SHA256)
  • ✅ Автоматическая установка обновлений
  • ✅ Откат к предыдущей версии при ошибках
  • ✅ Отправка статистики на сервер
  • ✅ Retry логика для скачивания
  • ✅ TypeScript поддержка
  • ✅ Event listeners для отслеживания процесса

Примеры использования

Только проверка обновлений

const ota = new OTAUpdate(config);
const response = await ota.checkOnly();

if (response.available && response.update) {
    // Показать диалог пользователю
    const shouldUpdate = await showUpdateDialog(response.update);

    if (shouldUpdate) {
        await ota.downloadAndInstall(response.update);
    }
}

Кастомная логика скачивания

const checker = new UpdateChecker(config);
const response = await checker.checkForUpdates();

if (response.available && response.update) {
    const downloader = new BundleDownloader();
    const bundlePath = await downloader.download(
        response.update,
        (progress) => {
            console.log(`${progress.progress * 100}%`);
        }
    );

    // Своя логика установки
    // ...
}

Откат при ошибке

try {
    await ota.checkAndInstall();
} catch (error) {
    console.error("Ошибка обновления:", error);

    // Автоматический откат уже выполнен
    // Но можно и вручную:
    const previousVersion = await ota.rollback();
    console.log("Откат к версии:", previousVersion);
}

Требования

  • React Native >= 0.70.0
  • TypeScript (рекомендуется)
  • Одна из библиотек для файловой системы:
    • react-native-fs (рекомендуется для bare React Native)
    • expo-file-system (для Expo проектов)
  • Одна из библиотек для криптографии:
    • react-native-crypto (рекомендуется)
    • crypto-js (легковесная альтернатива)
    • expo-crypto (для Expo проектов)

Troubleshooting

Ошибка "No crypto library available"

Установите одну из библиотек для криптографии:

npm install react-native-crypto
# или
npm install crypto-js

Ошибка "Neither react-native-fs nor expo-file-system is available"

Установите библиотеку для работы с файловой системой:

npm install react-native-fs
# Для iOS
cd ios && pod install

Ошибка "AsyncStorage not found"

Установите:

npm install @react-native-async-storage/async-storage

Bundle не применяется после установки

Убедитесь, что:

  1. Bundle файл скачан и проверен checksum
  2. Приложение перезапущено после установки
  3. Настроена загрузка bundle из правильной директории

Лицензия

MIT