UNPKG

@hot-updater/react-native

Version:

React Native OTA solution for self-hosted

146 lines (127 loc) 3.88 kB
import type { UpdateStatus } from "@hot-updater/core"; import { NativeEventEmitter } from "react-native"; import HotUpdaterNative, { type UpdateBundleParams, } from "./specs/NativeHotUpdater"; const NIL_UUID = "00000000-0000-0000-0000-000000000000"; declare const __HOT_UPDATER_BUNDLE_ID: string | undefined; export const HotUpdaterConstants = { HOT_UPDATER_BUNDLE_ID: __HOT_UPDATER_BUNDLE_ID || NIL_UUID, }; export type HotUpdaterEvent = { onProgress: { progress: number; }; }; export const addListener = <T extends keyof HotUpdaterEvent>( eventName: T, listener: (event: HotUpdaterEvent[T]) => void, ) => { const eventEmitter = new NativeEventEmitter(HotUpdaterNative); const subscription = eventEmitter.addListener(eventName, listener); return () => { subscription.remove(); }; }; export type UpdateParams = UpdateBundleParams & { status: UpdateStatus; }; /** * Downloads files and applies them to the app. * * @param {UpdateParams} params - Parameters object required for bundle update * @returns {Promise<boolean>} Resolves with true if download was successful, otherwise rejects with an error. */ export async function updateBundle(params: UpdateParams): Promise<boolean>; /** * @deprecated Use updateBundle(params: UpdateBundleParamsWithStatus) instead */ export async function updateBundle( bundleId: string, fileUrl: string | null, ): Promise<boolean>; export async function updateBundle( paramsOrBundleId: UpdateParams | string, fileUrl?: string | null, ): Promise<boolean> { const updateBundleId = typeof paramsOrBundleId === "string" ? paramsOrBundleId : paramsOrBundleId.bundleId; const status = typeof paramsOrBundleId === "string" ? "UPDATE" : paramsOrBundleId.status; const currentBundleId = getBundleId(); // updateBundleId <= currentBundleId if ( status === "UPDATE" && updateBundleId.localeCompare(currentBundleId) <= 0 ) { throw new Error( "Update bundle id is the same as the current bundle id. Preventing infinite update loop.", ); } if (typeof paramsOrBundleId === "string") { return HotUpdaterNative.updateBundle({ bundleId: updateBundleId, fileUrl: fileUrl || null, }); } return HotUpdaterNative.updateBundle({ bundleId: updateBundleId, fileUrl: paramsOrBundleId.fileUrl, }); } /** * Fetches the current app version. */ export const getAppVersion = (): string | null => { const constants = HotUpdaterNative.getConstants(); return constants?.APP_VERSION ?? null; }; /** * Reloads the app. */ export const reload = () => { requestAnimationFrame(() => { HotUpdaterNative.reload(); }); }; /** * Fetches the minimum bundle id, which represents the initial bundle of the app * since it is created at build time. * * @returns {string} Resolves with the minimum bundle id or null if not available. */ export const getMinBundleId = (): string => { const constants = HotUpdaterNative.getConstants(); return constants.MIN_BUNDLE_ID; }; /** * Fetches the current bundle version id. * * @async * @returns {Promise<string>} Resolves with the current version id or null if not available. */ export const getBundleId = (): string => { return HotUpdaterConstants.HOT_UPDATER_BUNDLE_ID === NIL_UUID ? getMinBundleId() : HotUpdaterConstants.HOT_UPDATER_BUNDLE_ID; }; /** * Fetches the channel for the app. * * @returns {string} Resolves with the channel or null if not available. */ export const getChannel = (): string => { const constants = HotUpdaterNative.getConstants(); return constants.CHANNEL; }; /** * Fetches the fingerprint for the app. * * @returns {string | null} Resolves with the fingerprint hash */ export const getFingerprintHash = (): string | null => { const constants = HotUpdaterNative.getConstants(); return constants.FINGERPRINT_HASH; };