UNPKG

@appzung/react-native-code-push

Version:

React Native plugin for the CodePush service

106 lines (92 loc) 4.38 kB
import { AppState, type NativeEventSubscription } from 'react-native'; import { LogLevel } from './enums/LogLevel.enum'; import { CodePushApiSdk } from './internals/CodePushApiSdk'; import { NativeRNAppZungCodePushModule } from './internals/NativeRNAppZungCodePushModule'; import { getConfiguration } from './internals/getConfiguration'; import { log } from './internals/utils/log'; import { requestFetchAdapter } from './internals/utils/requestFetchAdapter'; import type { StatusReport } from './types'; /** * @function * * Notifies the CodePush runtime that an installed update is considered successful. * * If you are manually checking for and installing updates (i.e. not using the `sync` method to handle it all for you), then this method **MUST** be called; otherwise CodePush will treat the update as failed and rollback to the previous version when the app next restarts. */ export const notifyAppReady = (() => { // This ensures that notifyApplicationReadyInternal is only called once // in the lifetime of this module instance. let notifyApplicationReadyPromise: Promise<StatusReport | void> | undefined; return () => { if (!notifyApplicationReadyPromise) { notifyApplicationReadyPromise = notifyApplicationReadyInternal(); } return notifyApplicationReadyPromise; }; })(); async function notifyApplicationReadyInternal() { log(LogLevel.DEBUG, 'notifyApplicationReady'); await NativeRNAppZungCodePushModule.notifyApplicationReady(); const statusReport = await NativeRNAppZungCodePushModule.getNewStatusReport(); if (statusReport) { log(LogLevel.DEBUG, `tryReportStatus ${statusReport.status || '(no update)'}`); tryReportStatus(statusReport); // Don't wait for this to complete. } else { log(LogLevel.DEBUG, `Nothing to report`); } return statusReport; } async function tryReportStatus(statusReport: StatusReport, retryOnAppResume?: NativeEventSubscription) { const config = await getConfiguration(); const previousLabelOrAppVersion = statusReport.previousLabelOrAppVersion ?? null; const previousReleaseChannelPublicId = statusReport.previousReleaseChannelPublicId || config.releaseChannelPublicId; try { if (statusReport.appVersion) { log(LogLevel.INFO, `Reporting binary update (${statusReport.appVersion})`); if (!config.releaseChannelPublicId) { throw new Error('Release channel is missing'); } const sdk = new CodePushApiSdk(requestFetchAdapter, log, config); await sdk.reportStatusDeploy(null, previousLabelOrAppVersion, previousReleaseChannelPublicId); } else { if (!statusReport.package) { throw new Error('Missing package in status report'); } const label = statusReport.package.label; if (statusReport.status === 'DeploymentSucceeded') { log(LogLevel.INFO, `Reporting CodePush update success (${label})`); } else { log(LogLevel.INFO, `Reporting CodePush update rollback (${label})`); await NativeRNAppZungCodePushModule.setLatestRollbackInfo(statusReport.package.packageHash); } config.releaseChannelPublicId = statusReport.package.releaseChannelPublicId; const sdk = new CodePushApiSdk(requestFetchAdapter, log, config); await sdk.reportStatusDeploy( { package: statusReport.package, status: statusReport.status, }, previousLabelOrAppVersion, previousReleaseChannelPublicId, ); } NativeRNAppZungCodePushModule.recordStatusReported(statusReport); retryOnAppResume && retryOnAppResume.remove(); } catch (e) { log(LogLevel.WARN, `Report status failed: ${JSON.stringify(statusReport)}`); NativeRNAppZungCodePushModule.saveStatusReportForRetry(statusReport); // Try again when the app resumes if (!retryOnAppResume) { const resumeListener = AppState.addEventListener('change', async (newState) => { if (newState !== 'active') return; const refreshedStatusReport = await NativeRNAppZungCodePushModule.getNewStatusReport(); if (refreshedStatusReport) { log(LogLevel.DEBUG, `tryReportStatus on active appState ${statusReport.status || '(no update)'}`); tryReportStatus(refreshedStatusReport, resumeListener); } else { resumeListener && resumeListener.remove(); } }); } } }