1import * as Updates from './Updates'; 2import type { 3 Manifest, 4 UpdatesNativeStateMachineContext, 5 UpdatesNativeStateRollback, 6} from './Updates.types'; 7import { UpdateInfoType, type CurrentlyRunningInfo, type UpdateInfo } from './UseUpdates.types'; 8 9// The currently running info, constructed from Updates constants 10export const currentlyRunning: CurrentlyRunningInfo = { 11 updateId: Updates.updateId ?? undefined, 12 channel: Updates.channel ?? undefined, 13 createdAt: Updates.createdAt ?? undefined, 14 isEmbeddedLaunch: Updates.isEmbeddedLaunch, 15 isEmergencyLaunch: Updates.isEmergencyLaunch, 16 manifest: Updates.manifest ?? undefined, 17 runtimeVersion: Updates.runtimeVersion ?? undefined, 18}; 19 20// Type for the state managed by useUpdates(). 21// Used internally by this module and not exported publicly. 22export type UseUpdatesStateType = { 23 availableUpdate?: UpdateInfo; 24 downloadedUpdate?: UpdateInfo; 25 checkError?: Error; 26 downloadError?: Error; 27 initializationError?: Error; 28 isUpdateAvailable: boolean; 29 isUpdatePending: boolean; 30 isChecking: boolean; 31 isDownloading: boolean; 32 lastCheckForUpdateTimeSinceRestart?: Date; 33}; 34 35// Constructs an UpdateInfo from a manifest 36export const updateFromManifest: (manifest: NonNullable<Manifest>) => UpdateInfo = (manifest) => { 37 return { 38 type: UpdateInfoType.NEW, 39 updateId: manifest.id ?? '', 40 createdAt: 41 manifest && 'createdAt' in manifest && manifest.createdAt 42 ? new Date(manifest.createdAt) 43 : // We should never reach this if the manifest is valid and has a commit time, 44 // but leave this in so that createdAt is always defined 45 new Date(0), 46 manifest, 47 }; 48}; 49 50export const updateFromRollback: (rollback: UpdatesNativeStateRollback) => UpdateInfo = ( 51 rollback 52) => ({ 53 type: UpdateInfoType.ROLLBACK, 54 createdAt: new Date(rollback.commitTime), 55 manifest: undefined, 56 updateId: undefined, 57}); 58 59// Default useUpdates() state 60export const defaultUseUpdatesState: UseUpdatesStateType = { 61 isChecking: false, 62 isDownloading: false, 63 isUpdateAvailable: false, 64 isUpdatePending: false, 65}; 66 67// Transform the useUpdates() state based on native state machine context 68export const reduceUpdatesStateFromContext: ( 69 updatesState: UseUpdatesStateType, 70 context: UpdatesNativeStateMachineContext 71) => UseUpdatesStateType = (updatesState, context) => { 72 const availableUpdate = context?.latestManifest 73 ? updateFromManifest(context?.latestManifest) 74 : context.rollback 75 ? updateFromRollback(context.rollback) 76 : undefined; 77 const downloadedUpdate = context?.downloadedManifest 78 ? updateFromManifest(context?.downloadedManifest) 79 : context.rollback 80 ? updateFromRollback(context.rollback) 81 : undefined; 82 return { 83 ...updatesState, 84 isUpdateAvailable: context.isUpdateAvailable, 85 isUpdatePending: context.isUpdatePending, 86 isChecking: context.isChecking, 87 isDownloading: context.isDownloading, 88 availableUpdate, 89 downloadedUpdate, 90 checkError: context.checkError, 91 downloadError: context.downloadError, 92 lastCheckForUpdateTimeSinceRestart: context.lastCheckForUpdateTime, 93 }; 94}; 95