expo-updates 1.0.0-canary-20250404-3c3b5fd → 29.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (280) hide show
  1. package/CHANGELOG.md +127 -0
  2. package/android/build.gradle +16 -7
  3. package/android/proguard-rules.pro +1 -1
  4. package/android/src/main/java/expo/modules/updates/DisabledUpdatesController.kt +48 -30
  5. package/android/src/main/java/expo/modules/updates/EnabledUpdatesController.kt +67 -36
  6. package/android/src/main/java/expo/modules/updates/IUpdatesController.kt +14 -12
  7. package/android/src/main/java/expo/modules/updates/UpdatesConfiguration.kt +80 -13
  8. package/android/src/main/java/expo/modules/updates/UpdatesConfigurationOverride.kt +29 -15
  9. package/android/src/main/java/expo/modules/updates/UpdatesController.kt +5 -1
  10. package/android/src/main/java/expo/modules/updates/UpdatesDevLauncherController.kt +93 -90
  11. package/android/src/main/java/expo/modules/updates/UpdatesModule.kt +104 -159
  12. package/android/src/main/java/expo/modules/updates/UpdatesPackage.kt +0 -26
  13. package/android/src/main/java/expo/modules/updates/UpdatesUtils.kt +4 -5
  14. package/android/src/main/java/expo/modules/updates/db/Converters.kt +22 -0
  15. package/android/src/main/java/expo/modules/updates/db/DatabaseHolder.kt +14 -23
  16. package/android/src/main/java/expo/modules/updates/db/UpdatesDatabase.kt +44 -24
  17. package/android/src/main/java/expo/modules/updates/db/dao/AssetDao.kt +16 -10
  18. package/android/src/main/java/expo/modules/updates/db/entity/AssetEntity.kt +9 -0
  19. package/android/src/main/java/expo/modules/updates/db/entity/UpdateEntity.kt +4 -1
  20. package/android/src/main/java/expo/modules/updates/launcher/DatabaseLauncher.kt +93 -83
  21. package/android/src/main/java/expo/modules/updates/launcher/NoDatabaseLauncher.kt +2 -2
  22. package/android/src/main/java/expo/modules/updates/loader/EmbeddedLoader.kt +34 -31
  23. package/android/src/main/java/expo/modules/updates/loader/FileDownloader.kt +357 -433
  24. package/android/src/main/java/expo/modules/updates/loader/Loader.kt +133 -174
  25. package/android/src/main/java/expo/modules/updates/loader/LoaderFiles.kt +7 -2
  26. package/android/src/main/java/expo/modules/updates/loader/LoaderTask.kt +192 -256
  27. package/android/src/main/java/expo/modules/updates/loader/RemoteLoader.kt +38 -55
  28. package/android/src/main/java/expo/modules/updates/manifest/EmbeddedManifestUtils.kt +36 -14
  29. package/android/src/main/java/expo/modules/updates/manifest/EmbeddedUpdate.kt +8 -3
  30. package/android/src/main/java/expo/modules/updates/manifest/ExpoUpdatesUpdate.kt +7 -3
  31. package/android/src/main/java/expo/modules/updates/procedures/CheckForUpdateProcedure.kt +120 -113
  32. package/android/src/main/java/expo/modules/updates/procedures/FetchUpdateProcedure.kt +72 -70
  33. package/android/src/main/java/expo/modules/updates/procedures/RecreateReactContextProcedure.kt +10 -5
  34. package/android/src/main/java/expo/modules/updates/procedures/RelaunchProcedure.kt +56 -41
  35. package/android/src/main/java/expo/modules/updates/procedures/StartupProcedure.kt +33 -50
  36. package/android/src/main/java/expo/modules/updates/procedures/StateMachineSerialExecutorQueue.kt +3 -1
  37. package/android/src/main/java/expo/modules/updates/reloadscreen/ReloadScreenConfiguration.kt +82 -0
  38. package/android/src/main/java/expo/modules/updates/reloadscreen/ReloadScreenManager.kt +100 -0
  39. package/android/src/main/java/expo/modules/updates/reloadscreen/ReloadScreenView.kt +162 -0
  40. package/android/src/main/java/expo/modules/updates/selectionpolicy/LauncherSelectionPolicyDevelopmentClient.kt +23 -0
  41. package/android/src/main/java/expo/modules/updates/selectionpolicy/LauncherSelectionPolicyFilterAware.kt +10 -13
  42. package/android/src/main/java/expo/modules/updates/selectionpolicy/LoaderSelectionPolicyDevelopmentClient.kt +80 -0
  43. package/android/src/main/java/expo/modules/updates/selectionpolicy/LoaderSelectionPolicyFilterAware.kt +26 -5
  44. package/android/src/main/java/expo/modules/updates/selectionpolicy/SelectionPolicyFactory.kt +5 -3
  45. package/android/src/main/java/expo/modules/updates/statemachine/UpdatesStateContext.kt +7 -0
  46. package/android/src/main/java/expo/modules/updates/statemachine/UpdatesStateEvent.kt +1 -0
  47. package/android/src/main/java/expo/modules/updates/statemachine/UpdatesStateEventType.kt +1 -0
  48. package/android/src/main/java/expo/modules/updates/statemachine/UpdatesStateMachine.kt +8 -2
  49. package/android/src/main/java/expo/modules/updates/utils/AndroidResourceAssetUtils.kt +120 -0
  50. package/android/src/shared/certificates/chainExpoProjectInformationViolationIntermediate.pem +24 -0
  51. package/android/src/shared/certificates/chainExpoProjectInformationViolationLeaf.pem +23 -0
  52. package/android/src/shared/certificates/chainExpoProjectInformationViolationRoot.pem +22 -0
  53. package/android/src/shared/certificates/chainIntermediate.pem +22 -0
  54. package/android/src/shared/certificates/chainLeaf.pem +23 -0
  55. package/android/src/shared/certificates/chainNotCAIntermediate.pem +22 -0
  56. package/android/src/shared/certificates/chainNotCALeaf.pem +23 -0
  57. package/android/src/shared/certificates/chainNotCARoot.pem +22 -0
  58. package/android/src/shared/certificates/chainPathLenViolationIntermediate.pem +22 -0
  59. package/android/src/shared/certificates/chainPathLenViolationLeaf.pem +23 -0
  60. package/android/src/shared/certificates/chainPathLenViolationRoot.pem +22 -0
  61. package/android/src/shared/certificates/chainRoot.pem +22 -0
  62. package/android/src/shared/certificates/invalidSignatureChainLeaf.pem +23 -0
  63. package/android/src/shared/certificates/noCodeSigningExtendedUsage.pem +17 -0
  64. package/android/src/shared/certificates/noKeyUsage.pem +17 -0
  65. package/android/src/shared/certificates/privatekeys/chainExpoProjectInformationViolationIntermediate-privateKey.pem +27 -0
  66. package/android/src/shared/certificates/privatekeys/chainExpoProjectInformationViolationLeaf-privateKey.pem +27 -0
  67. package/android/src/shared/certificates/privatekeys/chainExpoProjectInformationViolationRoot-privateKey.pem +27 -0
  68. package/android/src/shared/certificates/privatekeys/chainIntermediate-privateKey.pem +27 -0
  69. package/android/src/shared/certificates/privatekeys/chainLeaf-privateKey.pem +27 -0
  70. package/android/src/shared/certificates/privatekeys/chainNotCAIntermediate-privateKey.pem +27 -0
  71. package/android/src/shared/certificates/privatekeys/chainNotCALeaf-privateKey.pem +27 -0
  72. package/android/src/shared/certificates/privatekeys/chainNotCARoot-privateKey.pem +27 -0
  73. package/android/src/shared/certificates/privatekeys/chainPathLenViolationIntermediate-privateKey.pem +27 -0
  74. package/android/src/shared/certificates/privatekeys/chainPathLenViolationLeaf-privateKey.pem +27 -0
  75. package/android/src/shared/certificates/privatekeys/chainPathLenViolationRoot-privateKey.pem +27 -0
  76. package/android/src/shared/certificates/privatekeys/chainRoot-privateKey.pem +27 -0
  77. package/android/src/shared/certificates/privatekeys/noCodeSigningExtendedUsage-privateKey.pem +27 -0
  78. package/android/src/shared/certificates/privatekeys/noKeyUsage-privateKey.pem +27 -0
  79. package/android/src/shared/certificates/privatekeys/test-privateKey.pem +27 -0
  80. package/android/src/shared/certificates/privatekeys/validityExpired-privateKey.pem +27 -0
  81. package/android/src/shared/certificates/signatureInvalid.pem +18 -0
  82. package/android/src/shared/certificates/test.pem +18 -0
  83. package/android/src/shared/certificates/validityExpired.pem +17 -0
  84. package/build/ExpoUpdates.web.d.ts.map +1 -1
  85. package/build/ExpoUpdates.web.js +2 -1
  86. package/build/ExpoUpdates.web.js.map +1 -1
  87. package/build/ExpoUpdatesModule.types.d.ts +2 -2
  88. package/build/ExpoUpdatesModule.types.d.ts.map +1 -1
  89. package/build/ExpoUpdatesModule.types.js +1 -1
  90. package/build/ExpoUpdatesModule.types.js.map +1 -1
  91. package/build/ReloadScreen.types.d.ts +70 -0
  92. package/build/ReloadScreen.types.d.ts.map +1 -0
  93. package/build/ReloadScreen.types.js +2 -0
  94. package/build/ReloadScreen.types.js.map +1 -0
  95. package/build/Updates.d.ts +61 -3
  96. package/build/Updates.d.ts.map +1 -1
  97. package/build/Updates.js +103 -3
  98. package/build/Updates.js.map +1 -1
  99. package/build/Updates.types.d.ts +2 -0
  100. package/build/Updates.types.d.ts.map +1 -1
  101. package/build/Updates.types.js.map +1 -1
  102. package/build/UpdatesEmitter.d.ts.map +1 -1
  103. package/build/UpdatesEmitter.js.map +1 -1
  104. package/build/UseUpdates.types.d.ts +6 -0
  105. package/build/UseUpdates.types.d.ts.map +1 -1
  106. package/build/UseUpdates.types.js.map +1 -1
  107. package/build/UseUpdatesUtils.d.ts.map +1 -1
  108. package/build/UseUpdatesUtils.js +1 -0
  109. package/build/UseUpdatesUtils.js.map +1 -1
  110. package/cli/build/assetsVerify.js +17 -7
  111. package/cli/build/assetsVerifyAsync.js +7 -8
  112. package/cli/build/cli.js +17 -7
  113. package/cli/build/configureCodeSigning.js +17 -7
  114. package/cli/build/configureCodeSigningAsync.js +2 -3
  115. package/cli/build/generateCodeSigning.js +17 -7
  116. package/cli/build/generateCodeSigningAsync.js +1 -2
  117. package/cli/build/generateFingerprint.js +17 -7
  118. package/cli/build/resolveRuntimeVersion.js +17 -7
  119. package/cli/build/syncConfigurationToNative.js +17 -7
  120. package/cli/build/syncConfigurationToNativeAsync.js +5 -6
  121. package/cli/build/utils/args.js +20 -11
  122. package/cli/build/utils/dir.js +1 -2
  123. package/cli/build/utils/errors.js +2 -2
  124. package/cli/build/utils/log.js +8 -9
  125. package/cli/build/utils/modifyConfigAsync.d.ts +1 -1
  126. package/cli/build/utils/modifyConfigAsync.js +20 -11
  127. package/cli/build/utils/withConsoleDisabledAsync.js +1 -2
  128. package/cli/src/configureCodeSigningAsync.ts +1 -1
  129. package/cli/src/syncConfigurationToNativeAsync.ts +2 -2
  130. package/cli/src/utils/modifyConfigAsync.ts +2 -2
  131. package/e2e/README.md +17 -59
  132. package/e2e/fixtures/App.tsx +42 -6
  133. package/e2e/fixtures/custom_init/AppDelegate.swift +35 -18
  134. package/e2e/fixtures/project_files/.env +1 -0
  135. package/e2e/fixtures/project_files/maestro/maestro-test-executor.sh +60 -0
  136. package/e2e/fixtures/project_files/maestro/tests/assetRecovery_restoreAssetFiles.yml +81 -0
  137. package/e2e/fixtures/project_files/maestro/tests/basic_checkRequestHeaders.yml +19 -0
  138. package/e2e/fixtures/project_files/maestro/tests/basic_reload.yml +32 -0
  139. package/e2e/fixtures/project_files/maestro/tests/basic_rollback.yml +90 -0
  140. package/e2e/fixtures/project_files/maestro/tests/basic_runUpdate.yml +30 -0
  141. package/e2e/fixtures/project_files/maestro/tests/basic_startAndStop.yml +24 -0
  142. package/e2e/fixtures/project_files/maestro/tests/basic_updateInvalidAssetHash.yml +48 -0
  143. package/e2e/fixtures/project_files/maestro/tests/basic_updateInvalidHash.yml +30 -0
  144. package/e2e/fixtures/project_files/maestro/tests/basic_updateMultipleAssets.yml +33 -0
  145. package/e2e/fixtures/project_files/maestro/tests/basic_updateOldCommitTime.yml +33 -0
  146. package/e2e/fixtures/project_files/maestro/tests/beforeEach.yml +23 -0
  147. package/e2e/fixtures/project_files/maestro/tests/brickingDisabled_jsReloadUpdate.yml +47 -0
  148. package/e2e/fixtures/project_files/maestro/tests/brickingDisabled_runUpdate.yml +42 -0
  149. package/e2e/fixtures/project_files/maestro/tests/devClient_runUpdate.yml +42 -0
  150. package/e2e/fixtures/project_files/maestro/tests/devClient_verifyState.yml +41 -0
  151. package/e2e/fixtures/project_files/maestro/tests/disabled_verifyState.yml +61 -0
  152. package/e2e/fixtures/project_files/maestro/tests/errorRecovery_runUpdate.yml +67 -0
  153. package/e2e/fixtures/project_files/maestro/tests/fingerprint_runUpdate.yml +21 -0
  154. package/e2e/fixtures/project_files/maestro/tests/jsapi_runUpdate.yml +110 -0
  155. package/e2e/fixtures/project_files/maestro/tests/jsapi_setRequestHeadersOverride.yml +130 -0
  156. package/e2e/fixtures/project_files/maestro/tests/jsapi_stateMachine.yml +218 -0
  157. package/e2e/fixtures/project_files/maestro/tests/maestroUpdatesApi.js +77 -0
  158. package/e2e/fixtures/project_files/maestro/tests/startup_runFastUpdate.yml +19 -0
  159. package/e2e/fixtures/project_files/maestro/tests/startup_runSlowUpdate.yml +24 -0
  160. package/e2e/fixtures/project_files/maestro/tests/updates-e2e-bricking-measures-disabled.yml +6 -0
  161. package/e2e/fixtures/project_files/maestro/tests/updates-e2e-dev-client.yml +6 -0
  162. package/e2e/fixtures/project_files/maestro/tests/updates-e2e-disabled.yml +6 -0
  163. package/e2e/fixtures/project_files/maestro/tests/updates-e2e-enabled.yml +28 -0
  164. package/e2e/fixtures/project_files/maestro/tests/updates-e2e-error-recovery.yml +4 -0
  165. package/e2e/fixtures/project_files/maestro/tests/updates-e2e-fingerprint.yml +4 -0
  166. package/e2e/fixtures/project_files/maestro/tests/updates-e2e-startup.yml +6 -0
  167. package/e2e/fixtures/project_files/maestro/updates-server/server.ts +829 -0
  168. package/e2e/fixtures/project_files/maestro/updates-server/start.ts +17 -0
  169. package/e2e/fixtures/project_files/{e2e/tests/utils → maestro/updates-server}/update.ts +20 -13
  170. package/e2e/fixtures/project_files/scripts/check-android-emulator.ts +44 -0
  171. package/e2e/fixtures/project_files/scripts/generate-test-update-bundles.ts +9 -1
  172. package/e2e/setup/create-bricking-measures-disabled-eas-project.ts +3 -4
  173. package/e2e/setup/create-dev-client-eas-project.ts +12 -8
  174. package/e2e/setup/create-disabled-eas-project.ts +3 -3
  175. package/e2e/setup/create-eas-project-custom-init.ts +3 -5
  176. package/e2e/setup/create-eas-project-old-arch.ts +43 -0
  177. package/e2e/setup/create-eas-project-tv.ts +21 -8
  178. package/e2e/setup/create-eas-project.ts +3 -5
  179. package/e2e/setup/create-error-recovery-eas-project.ts +3 -4
  180. package/e2e/setup/create-fingerprint-eas-project.ts +3 -4
  181. package/e2e/setup/create-startup-eas-project.ts +3 -4
  182. package/e2e/setup/create-updates-test.ts +3 -5
  183. package/e2e/setup/project.ts +92 -105
  184. package/e2e/tsconfig.json +4 -0
  185. package/expo-updates-gradle-plugin/src/main/kotlin/expo/modules/updates/ExpoUpdatesPlugin.kt +9 -4
  186. package/ios/EXUpdates/AppController.swift +3 -0
  187. package/ios/EXUpdates/AppLauncher/AppLauncherWithDatabase.swift +12 -9
  188. package/ios/EXUpdates/AppLoader/AppLoader.swift +31 -3
  189. package/ios/EXUpdates/AppLoader/AppLoaderTask.swift +1 -1
  190. package/ios/EXUpdates/AppLoader/EmbeddedAppLoader.swift +29 -5
  191. package/ios/EXUpdates/AppLoader/FileDownloader.swift +23 -5
  192. package/ios/EXUpdates/AppLoader/RemoteAppLoader.swift +65 -41
  193. package/ios/EXUpdates/CodeSigning/CodeSigningConfiguration.swift +2 -3
  194. package/ios/EXUpdates/Database/Migrations/UpdatesDatabaseMigration10To11.swift +21 -0
  195. package/ios/EXUpdates/Database/Migrations/UpdatesDatabaseMigrationRegistry.swift +2 -1
  196. package/ios/EXUpdates/Database/UpdatesDatabase.swift +27 -5
  197. package/ios/EXUpdates/Database/UpdatesDatabaseInitialization.swift +3 -1
  198. package/ios/EXUpdates/DevLauncherAppController.swift +11 -2
  199. package/ios/EXUpdates/DisabledAppController.swift +6 -0
  200. package/ios/EXUpdates/EnabledAppController.swift +28 -9
  201. package/ios/EXUpdates/Exceptions.swift +17 -0
  202. package/ios/EXUpdates/Multipart/EXUpdatesMultipartStreamReader.h +3 -2
  203. package/ios/EXUpdates/Multipart/EXUpdatesMultipartStreamReader.m +2 -2
  204. package/ios/EXUpdates/Procedures/FetchUpdateProcedure.swift +4 -1
  205. package/ios/EXUpdates/Procedures/RelaunchProcedure.swift +5 -0
  206. package/ios/EXUpdates/ReactDelegateHandler/EXDeferredRCTRootView.h +1 -1
  207. package/ios/EXUpdates/ReactDelegateHandler/EXDeferredRCTRootView.m +1 -0
  208. package/ios/EXUpdates/ReactDelegateHandler/ExpoUpdatesReactDelegateHandler.swift +27 -4
  209. package/ios/EXUpdates/ReloadScreen/ReloadExceptions.swift +7 -0
  210. package/ios/EXUpdates/ReloadScreen/ReloadScreenConfiguration.swift +114 -0
  211. package/ios/EXUpdates/ReloadScreen/ReloadScreenManager.swift +101 -0
  212. package/ios/EXUpdates/ReloadScreen/ReloadScreenManagerMacOS.swift +104 -0
  213. package/ios/EXUpdates/ReloadScreen/ReloadScreenView.swift +175 -0
  214. package/ios/EXUpdates/ReloadScreen/ReloadScreenViewMacOS.swift +173 -0
  215. package/ios/EXUpdates/ReloadScreen/Reloadable.swift +5 -0
  216. package/ios/EXUpdates/SelectionPolicy/LauncherSelectionPolicyDevelopmentClient.swift +25 -0
  217. package/ios/EXUpdates/SelectionPolicy/LauncherSelectionPolicyFilterAware.swift +7 -17
  218. package/ios/EXUpdates/SelectionPolicy/LoaderSelectionPolicyDevelopmentClient.swift +80 -0
  219. package/ios/EXUpdates/SelectionPolicy/LoaderSelectionPolicyFilterAware.swift +27 -1
  220. package/ios/EXUpdates/SelectionPolicy/SelectionPolicyFactory.swift +3 -3
  221. package/ios/EXUpdates/Update/EmbeddedUpdate.swift +3 -1
  222. package/ios/EXUpdates/Update/ExpoUpdatesUpdate.swift +3 -1
  223. package/ios/EXUpdates/Update/Update.swift +7 -1
  224. package/ios/EXUpdates/UpdatesConfig.swift +76 -5
  225. package/ios/EXUpdates/UpdatesConfigOverride.swift +12 -2
  226. package/ios/EXUpdates/UpdatesModule.swift +24 -2
  227. package/ios/EXUpdates/UpdatesStateMachine.swift +18 -1
  228. package/ios/EXUpdates.podspec +3 -2
  229. package/ios/Tests/AppLauncherWithDatabaseSpec.swift +10 -8
  230. package/ios/Tests/DatabaseInitializationSpec.swift +95 -0
  231. package/ios/Tests/DatabaseIntegrityCheckSpec.swift +17 -9
  232. package/ios/Tests/ErrorRecoverySpec.swift +6 -2
  233. package/ios/Tests/FileDownloaderSpec.swift +111 -4
  234. package/ios/Tests/LauncherSelectionPolicyFilterAwareSpec.swift +179 -0
  235. package/ios/Tests/LoaderSelectionPolicyFilterAwareSpec.swift +201 -0
  236. package/ios/Tests/ReaperSelectionPolicyDevelopmentClientSpec.swift +15 -5
  237. package/ios/Tests/ReaperSelectionPolicyFilterAwareSpec.swift +18 -6
  238. package/ios/Tests/SelectionPolicyFilterAwareSpec.swift +1 -1
  239. package/ios/Tests/UpdatesBuildDataSpec.swift +1 -1
  240. package/ios/Tests/UpdatesConfigOverrideSpec.swift +130 -0
  241. package/ios/Tests/UpdatesConfigSpec.swift +57 -0
  242. package/ios/Tests/UpdatesDatabaseSpec.swift +42 -4
  243. package/ios/Tests/UpdatesStateMachineSpec.swift +17 -0
  244. package/package.json +22 -14
  245. package/scripts/create-updates-resources-ios.sh +11 -1
  246. package/src/ExpoUpdates.web.ts +2 -1
  247. package/src/ExpoUpdatesModule.types.ts +2 -1
  248. package/src/ReloadScreen.types.ts +80 -0
  249. package/src/Updates.ts +119 -3
  250. package/src/Updates.types.ts +3 -0
  251. package/src/UseUpdates.types.ts +6 -0
  252. package/src/UseUpdatesUtils.ts +1 -0
  253. package/utils/build/createFingerprintAsync.js +18 -9
  254. package/utils/build/createFingerprintForBuildAsync.js +2 -3
  255. package/utils/build/createManifestForBuildAsync.js +8 -9
  256. package/utils/build/filterPlatformAssetScales.js +1 -2
  257. package/utils/build/findUpProjectRoot.js +1 -2
  258. package/utils/build/resolveRuntimeVersionAsync.js +3 -4
  259. package/utils/build/vcs.js +1 -1
  260. package/utils/build/workflow.js +3 -4
  261. package/utils/src/createFingerprintForBuildAsync.ts +1 -1
  262. package/utils/src/createManifestForBuildAsync.ts +9 -13
  263. package/utils/src/resolveRuntimeVersionAsync.ts +2 -2
  264. package/utils/src/workflow.ts +1 -1
  265. package/e2e/fixtures/Updates-bricking-measures-disabled.e2e.ts +0 -77
  266. package/e2e/fixtures/Updates-dev-client.e2e.ts +0 -77
  267. package/e2e/fixtures/Updates-disabled.e2e.ts +0 -78
  268. package/e2e/fixtures/Updates-error-recovery.e2e.ts +0 -103
  269. package/e2e/fixtures/Updates-fingerprint.e2e.ts +0 -73
  270. package/e2e/fixtures/Updates-startup.e2e.ts +0 -104
  271. package/e2e/fixtures/Updates.e2e.ts +0 -1016
  272. package/e2e/fixtures/project_files/.detoxrc.json +0 -68
  273. package/e2e/fixtures/project_files/e2e/jest.config.js +0 -12
  274. package/e2e/fixtures/project_files/e2e/tests/utils/server.ts +0 -303
  275. package/e2e/fixtures/project_files/eas-hooks/eas-build-on-success.sh +0 -83
  276. package/e2e/fixtures/project_files/eas-hooks/eas-build-pre-install.sh +0 -43
  277. package/utils/ts-declarations/expo__cli/index.d.ts +0 -2
  278. /package/e2e/fixtures/project_files/{e2e/tests → maestro/updates-server}/assets/lubo-minar-j2RgHfqKhCM-unsplash.jpg +0 -0
  279. /package/e2e/fixtures/project_files/{e2e/tests → maestro/updates-server}/assets/niklas-liniger-zuPiCN7xekM-unsplash.jpg +0 -0
  280. /package/e2e/fixtures/project_files/{e2e/tests → maestro/updates-server}/assets/patrick-untersee-XJjsuuDwWas-unsplash.jpg +0 -0
package/CHANGELOG.md CHANGED
@@ -4,6 +4,133 @@
4
4
 
5
5
  ### 🛠 Breaking changes
6
6
 
7
+ ### 🎉 New features
8
+
9
+ ### 🐛 Bug fixes
10
+
11
+ ### 💡 Others
12
+
13
+ ## 29.0.0 — 2025-08-13
14
+
15
+ ### 🎉 New features
16
+
17
+ - Add experimental support for macOS. ([#37629](https://github.com/expo/expo/pull/37629) by [@gabrieldonadel](https://github.com/gabrieldonadel))
18
+ - Add support for a customisable reloading view when `reloadAsync` is called. ([#38074](https://github.com/expo/expo/pull/38074) by [@alanjhughes](https://github.com/alanjhughes)), ([#38362](https://github.com/expo/expo/pull/38362) by [@alanjhughes](https://github.com/alanjhughes)) and ([#38409](https://github.com/expo/expo/pull/38409) by [@gabrieldonadel](https://github.com/gabrieldonadel))
19
+ - Add `downloadProgress` state to the `useUpdates` hook to support listening to overall asset download progress. ([#38307](https://github.com/expo/expo/pull/38307)) by [@nishan](https://github.com/intergalacticspacehighway)
20
+ - [iOS] dev-client support for Apple TV. ([#38388](https://github.com/expo/expo/pull/38388) by [@douglowder](https://github.com/douglowder))
21
+ - Added reload support to `setUpdateURLAndRequestHeadersOverride`. ([#38167](https://github.com/expo/expo/pull/38167), [#38180](https://github.com/expo/expo/pull/38180) by [@kudo](https://github.com/kudo))
22
+ - Added `setUpdateRequestHeadersOverride` to allow runtime `requestHeaders` override. ([#38623](https://github.com/expo/expo/pull/38623), [#38628](https://github.com/expo/expo/pull/38628), [#38624](https://github.com/expo/expo/pull/38624) by [@kudo](https://github.com/kudo))
23
+
24
+ ### 🐛 Bug fixes
25
+
26
+ - Fixed imports after upgrading to Metro 0.83 ([#38375](https://github.com/expo/expo/pull/38375) by [@chrfalch](https://github.com/chrfalch))
27
+
28
+ ### 💡 Others
29
+
30
+ - [Android] Cleanup state machine resources when the module is destroyed. ([#37193](https://github.com/expo/expo/pull/37193) by [@alanjhughes](https://github.com/alanjhughes))
31
+ - [CI] convert E2E (enabled) tests to Maestro. ([#37492](https://github.com/expo/expo/pull/37492) by [@douglowder](https://github.com/douglowder))
32
+ - [CI] convert E2E (disabled) tests to Maestro. ([#37558](https://github.com/expo/expo/pull/37558) by [@douglowder](https://github.com/douglowder))
33
+ - [CI] convert E2E (fingerprint and startup) tests to Maestro. ([#37592](https://github.com/expo/expo/pull/37592) by [@douglowder](https://github.com/douglowder))
34
+ - [CI] convert E2E (old arch, custom init, error recovery, bricking measures disabled) tests to Maestro. ([#37600](https://github.com/expo/expo/pull/37600) by [@douglowder](https://github.com/douglowder))
35
+ - Bump Express and types to `express@5`. ([#37635](https://github.com/expo/expo/pull/37635) by [@byCedric](https://github.com/byCedric))
36
+ - [CI] Removed Detox testing workaround code on Android. ([#37707](https://github.com/expo/expo/pull/37707) by [@kudo](https://github.com/kudo))
37
+ - [CI] Removed Detox dependency and unused files in E2E code. ([#37751](https://github.com/expo/expo/pull/37751) by [@douglowder](https://github.com/douglowder))
38
+ - Updates imports from `@expo/config`, `@expo/config-plugins` to `expo/config`, `expo/config-plugins`. ([#37860](https://github.com/expo/expo/pull/37860) by [@aleqsio](https://github.com/aleqsio))
39
+ - [Android] Migrate loaders and file downloader to coroutines. ([#37959](https://github.com/expo/expo/pull/37959) by [@alanjhughes](https://github.com/alanjhughes))
40
+ - [Android] Fix procedure scope no surviving app reloads. ([#38073](https://github.com/expo/expo/pull/38073) by [@alanjhughes](https://github.com/alanjhughes))
41
+ - [Internal] Replace dependency chain to `@expo/cli` internals with an internal entrypoint ([#38574](https://github.com/expo/expo/pull/38574) by [@kitten](https://github.com/kitten))
42
+
43
+ ### 📚 3rd party library updates
44
+
45
+ - Bumped `form-data@4.0.4`. ([#38214](https://github.com/expo/expo/pull/38214) by [@kudo](https://github.com/kudo))
46
+
47
+ ## 0.28.17 - 2025-07-08
48
+
49
+ _This version does not introduce any user-facing changes._
50
+
51
+ ## 0.28.16 - 2025-07-03
52
+
53
+ _This version does not introduce any user-facing changes._
54
+
55
+ ## 0.28.15 - 2025-06-18
56
+
57
+ ### 🐛 Bug fixes
58
+
59
+ - Fix updates native debug for iOS. ([#37323](https://github.com/expo/expo/pull/37323) by [@douglowder](https://github.com/douglowder))
60
+
61
+ ## 0.28.14 - 2025-06-04
62
+
63
+ ### 🐛 Bug fixes
64
+
65
+ - Fix update failure reason not populated on iOS. ([#36893](https://github.com/expo/expo/pull/36893) by [@brainbicycle](https://github.com/brainbicycle))
66
+
67
+ ### 💡 Others
68
+
69
+ - Remove "Please" from warnings and errors ([#36862](https://github.com/expo/expo/pull/36862) by [@brentvatne](https://github.com/brentvatne))
70
+
71
+ ## 0.28.13 — 2025-05-08
72
+
73
+ ### 🐛 Bug fixes
74
+
75
+ - [Android] Fixed errors when `configuration-cache` is enabled. ([#36678](https://github.com/expo/expo/pull/36678) by [@lukmccall](https://github.com/lukmccall))
76
+ - [iOS] Update the constraints of the deferred root view. ([#36744](https://github.com/expo/expo/pull/36744) by [@alanjhughes](https://github.com/alanjhughes))
77
+
78
+ ## 0.28.12 — 2025-05-01
79
+
80
+ _This version does not introduce any user-facing changes._
81
+
82
+ ## 0.28.11 — 2025-04-30
83
+
84
+ _This version does not introduce any user-facing changes._
85
+
86
+ ## 0.28.10 — 2025-04-30
87
+
88
+ _This version does not introduce any user-facing changes._
89
+
90
+ ## 0.28.9 — 2025-04-28
91
+
92
+ _This version does not introduce any user-facing changes._
93
+
94
+ ## 0.28.8 — 2025-04-28
95
+
96
+ _This version does not introduce any user-facing changes._
97
+
98
+ ## 0.28.7 — 2025-04-25
99
+
100
+ ### 🐛 Bug fixes
101
+
102
+ - Fixed build error from **AppDelegate.swift** integration. ([#36368](https://github.com/expo/expo/pull/36368) by [@kudo](https://github.com/kudo))
103
+
104
+ ## 0.28.6 — 2025-04-22
105
+
106
+ _This version does not introduce any user-facing changes._
107
+
108
+ ## 0.28.5 — 2025-04-14
109
+
110
+ _This version does not introduce any user-facing changes._
111
+
112
+ ## 0.28.4 — 2025-04-14
113
+
114
+ ### 🎉 New features
115
+
116
+ - [Android] Added `EX_UPDATES_COPY_EMBEDDED_ASSETS` flag which is false by default, to not copy embedded assets. ([#36059](https://github.com/expo/expo/pull/36059) by [@kudo](https://github.com/kudo))
117
+
118
+ ## 0.28.3 — 2025-04-11
119
+
120
+ _This version does not introduce any user-facing changes._
121
+
122
+ ## 0.28.2 — 2025-04-09
123
+
124
+ _This version does not introduce any user-facing changes._
125
+
126
+ ## 0.28.1 — 2025-04-08
127
+
128
+ _This version does not introduce any user-facing changes._
129
+
130
+ ## 0.28.0 — 2025-04-04
131
+
132
+ ### 🛠 Breaking changes
133
+
7
134
  - upgrade RN to 0.78 ([#35050](https://github.com/expo/expo/pull/35050) by [@vonovak](https://github.com/vonovak))
8
135
  - Remove a few long-deprecated typescript types. ([#34215](https://github.com/expo/expo/pull/34215) by [@wschurman](https://github.com/wschurman))
9
136
 
@@ -11,7 +11,10 @@ buildscript {
11
11
  // We can remove this path once we update the test environment
12
12
  // to use the same version of Kotlin as the `expo/expo` repo.
13
13
  def kotlinVersion = rootProject["kotlinVersion"]
14
- if (kotlinVersion == "2.0.21") {
14
+
15
+ if (kotlinVersion == "2.1.20") {
16
+ return "2.1.20-2.0.1"
17
+ } else if (kotlinVersion == "2.0.21") {
15
18
  return "2.0.21-1.0.28"
16
19
  } else if (kotlinVersion == "1.9.25") {
17
20
  return "1.9.25-1.0.20"
@@ -39,7 +42,7 @@ expoModule {
39
42
  }
40
43
 
41
44
  group = 'host.exp.exponent'
42
- version = '0.26.9'
45
+ version = '29.0.0'
43
46
 
44
47
  // Utility method to derive boolean values from the environment or from Java properties,
45
48
  // and return them as strings to be used in BuildConfig fields
@@ -72,6 +75,9 @@ def exUpdatesCustomInit = getBoolStringFromPropOrEnv("EX_UPDATES_CUSTOM_INIT", f
72
75
  // (default true)
73
76
  def exUpdatesAndroidDelayLoadApp = getBoolStringFromPropOrEnv("EX_UPDATES_ANDROID_DELAY_LOAD_APP", true)
74
77
 
78
+ // If true, updates will copy embedded assets to file system when startup. (default false)
79
+ def exUpdatesCopyEmbeddedAssets = getBoolStringFromPropOrEnv("EX_UPDATES_COPY_EMBEDDED_ASSETS", false)
80
+
75
81
  def useDevClient = findProject(":expo-dev-client") != null
76
82
 
77
83
  android {
@@ -82,13 +88,14 @@ android {
82
88
  namespace "expo.modules.updates"
83
89
  defaultConfig {
84
90
  versionCode 31
85
- versionName '0.26.9'
91
+ versionName '29.0.0'
86
92
  consumerProguardFiles("proguard-rules.pro")
87
93
  testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
88
94
 
89
95
  buildConfigField("boolean", "EX_UPDATES_NATIVE_DEBUG", exUpdatesNativeDebug)
90
96
  buildConfigField("boolean", "EX_UPDATES_CUSTOM_INIT", exUpdatesCustomInit)
91
97
  buildConfigField("boolean", "EX_UPDATES_ANDROID_DELAY_LOAD_APP", exUpdatesAndroidDelayLoadApp)
98
+ buildConfigField("boolean", "EX_UPDATES_COPY_EMBEDDED_ASSETS", exUpdatesCopyEmbeddedAssets)
92
99
  buildConfigField("boolean", "USE_DEV_CLIENT", useDevClient.toString())
93
100
  }
94
101
  testOptions {
@@ -127,6 +134,7 @@ dependencies {
127
134
  def mockk_version = "1.13.11"
128
135
 
129
136
  implementation "androidx.room:room-runtime:$room_version"
137
+ implementation "androidx.room:room-ktx:$room_version"
130
138
  ksp "androidx.room:room-compiler:$room_version"
131
139
 
132
140
  implementation("com.squareup.okhttp3:okhttp:4.9.2")
@@ -135,16 +143,17 @@ dependencies {
135
143
  implementation("org.bouncycastle:bcutil-jdk15to18:1.78.1")
136
144
 
137
145
  testImplementation 'junit:junit:4.13.2'
138
- testImplementation 'androidx.test:core:1.5.0'
146
+ testImplementation 'androidx.test:core:1.6.1'
147
+ testImplementation 'com.google.truth:truth:1.1.2'
139
148
  testImplementation "io.mockk:mockk:$mockk_version"
140
149
  testImplementation "org.jetbrains.kotlin:kotlin-test-junit:${kotlinVersion}"
141
150
  testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3'
142
151
  testImplementation 'org.robolectric:robolectric:4.14.1'
143
152
 
144
153
  androidTestImplementation 'com.squareup.okio:okio:2.9.0'
145
- androidTestImplementation 'androidx.test:runner:1.5.2'
146
- androidTestImplementation 'androidx.test:core:1.5.0'
147
- androidTestImplementation 'androidx.test:rules:1.5.0'
154
+ androidTestImplementation 'androidx.test:runner:1.6.2'
155
+ androidTestImplementation 'androidx.test:core:1.6.1'
156
+ androidTestImplementation 'androidx.test:rules:1.6.1'
148
157
  androidTestImplementation "io.mockk:mockk-android:$mockk_version"
149
158
  androidTestImplementation "androidx.room:room-testing:$room_version"
150
159
  androidTestImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3'
@@ -3,5 +3,5 @@
3
3
  }
4
4
 
5
5
  -keepclassmembers class com.facebook.react.devsupport.ReleaseDevSupportManager {
6
- private final com.facebook.react.bridge.DefaultJSExceptionHandler defaultJSExceptionHandler;
6
+ private final com.facebook.react.bridge.JSExceptionHandler defaultJSExceptionHandler;
7
7
  }
@@ -11,13 +11,24 @@ import expo.modules.updates.events.IUpdatesEventManager
11
11
  import expo.modules.updates.events.UpdatesEventManager
12
12
  import expo.modules.updates.launcher.Launcher
13
13
  import expo.modules.updates.launcher.NoDatabaseLauncher
14
- import expo.modules.updates.logging.UpdatesErrorCode
15
14
  import expo.modules.updates.logging.UpdatesLogger
16
15
  import expo.modules.updates.procedures.RecreateReactContextProcedure
16
+ import expo.modules.updates.reloadscreen.ReloadScreenManager
17
17
  import expo.modules.updates.statemachine.UpdatesStateMachine
18
18
  import expo.modules.updates.statemachine.UpdatesStateValue
19
+ import kotlinx.coroutines.CompletableDeferred
20
+ import kotlinx.coroutines.CoroutineScope
21
+ import kotlinx.coroutines.Dispatchers
22
+ import kotlinx.coroutines.cancel
23
+ import kotlinx.coroutines.launch
24
+ import kotlinx.coroutines.runBlocking
25
+ import kotlinx.coroutines.suspendCancellableCoroutine
26
+ import kotlinx.coroutines.sync.Mutex
27
+ import kotlinx.coroutines.sync.withLock
19
28
  import java.io.File
20
29
  import java.lang.ref.WeakReference
30
+ import kotlin.coroutines.resume
31
+ import kotlin.coroutines.resumeWithException
21
32
  import kotlin.time.DurationUnit
22
33
  import kotlin.time.toDuration
23
34
 
@@ -34,6 +45,7 @@ class DisabledUpdatesController(
34
45
  ) : IUpdatesController {
35
46
  /** Keep the activity for [RecreateReactContextProcedure] to relaunch the app. */
36
47
  private var weakActivity: WeakReference<Activity>? = null
48
+ private val controllerScope = CoroutineScope(Dispatchers.IO)
37
49
 
38
50
  private val logger = UpdatesLogger(context.filesDir)
39
51
  override val eventManager: IUpdatesEventManager = UpdatesEventManager(logger)
@@ -55,24 +67,22 @@ class DisabledUpdatesController(
55
67
  }
56
68
 
57
69
  private var launcher: Launcher? = null
58
- private var isLoaderTaskFinished = false
59
70
  override var updatesDirectory: File? = null
71
+ private val loaderTaskFinishedDeferred = CompletableDeferred<Unit>()
72
+ private val loaderTaskFinishedMutex = Mutex()
60
73
 
61
- @get:Synchronized
62
74
  override val launchAssetFile: String?
63
75
  get() {
64
- while (!isLoaderTaskFinished) {
65
- try {
66
- (this as java.lang.Object).wait()
67
- } catch (e: InterruptedException) {
68
- logger.error("Interrupted while waiting for launch asset file", e, UpdatesErrorCode.InitializationError)
69
- }
76
+ runBlocking {
77
+ loaderTaskFinishedDeferred.await()
70
78
  }
71
79
  return launcher?.launchAssetFile
72
80
  }
73
81
 
74
82
  override val bundleAssetName: String?
75
83
  get() = launcher?.bundleAssetName
84
+ override val reloadScreenManager: ReloadScreenManager?
85
+ get() = null
76
86
 
77
87
  override fun onEventListenerStartObserving() {
78
88
  stateMachine.sendContextToJS()
@@ -121,58 +131,66 @@ class DisabledUpdatesController(
121
131
  )
122
132
  }
123
133
 
124
- override fun relaunchReactApplicationForModule(callback: IUpdatesController.ModuleCallback<Unit>) {
134
+ override suspend fun relaunchReactApplicationForModule() = suspendCancellableCoroutine { continuation ->
125
135
  val procedure = RecreateReactContextProcedure(
126
136
  context,
127
137
  weakActivity,
128
138
  object : Launcher.LauncherCallback {
129
139
  override fun onFailure(e: Exception) {
130
- callback.onFailure(e.toCodedException())
140
+ continuation.resumeWithException(e.toCodedException())
131
141
  }
132
142
 
133
143
  override fun onSuccess() {
134
- callback.onSuccess(Unit)
144
+ continuation.resume(Unit)
135
145
  }
136
146
  }
137
147
  )
138
148
  stateMachine.queueExecution(procedure)
139
149
  }
140
150
 
141
- override fun checkForUpdate(
142
- callback: IUpdatesController.ModuleCallback<IUpdatesController.CheckForUpdateResult>
143
- ) {
144
- callback.onFailure(UpdatesDisabledException("Updates.checkForUpdateAsync() is not supported when expo-updates is not enabled."))
151
+ override suspend fun checkForUpdate(): IUpdatesController.CheckForUpdateResult {
152
+ throw UpdatesDisabledException("Updates.checkForUpdateAsync() is not supported when expo-updates is not enabled.")
145
153
  }
146
154
 
147
- override fun fetchUpdate(
148
- callback: IUpdatesController.ModuleCallback<IUpdatesController.FetchUpdateResult>
149
- ) {
150
- callback.onFailure(UpdatesDisabledException("Updates.fetchUpdateAsync() is not supported when expo-updates is not enabled."))
155
+ override suspend fun fetchUpdate(): IUpdatesController.FetchUpdateResult {
156
+ throw UpdatesDisabledException("Updates.fetchUpdateAsync() is not supported when expo-updates is not enabled.")
151
157
  }
152
158
 
153
- override fun getExtraParams(callback: IUpdatesController.ModuleCallback<Bundle>) {
154
- callback.onFailure(UpdatesDisabledException("Updates.getExtraParamsAsync() is not supported when expo-updates is not enabled."))
159
+ override suspend fun getExtraParams(): Bundle {
160
+ throw UpdatesDisabledException("Updates.getExtraParamsAsync() is not supported when expo-updates is not enabled.")
155
161
  }
156
162
 
157
- override fun setExtraParam(
163
+ override suspend fun setExtraParam(
158
164
  key: String,
159
- value: String?,
160
- callback: IUpdatesController.ModuleCallback<Unit>
165
+ value: String?
161
166
  ) {
162
- callback.onFailure(UpdatesDisabledException("Updates.setExtraParamAsync() is not supported when expo-updates is not enabled."))
167
+ throw UpdatesDisabledException("Updates.setExtraParamAsync() is not supported when expo-updates is not enabled.")
163
168
  }
164
169
 
165
170
  override fun setUpdateURLAndRequestHeadersOverride(configOverride: UpdatesConfigurationOverride?) {
166
171
  throw UpdatesDisabledException("Updates.setUpdateURLAndRequestHeadersOverride() is not supported when expo-updates is not enabled.")
167
172
  }
168
173
 
174
+ override fun setUpdateRequestHeadersOverride(requestHeaders: Map<String, String>?) {
175
+ throw UpdatesDisabledException("Updates.setUpdateRequestHeadersOverride() is not supported when expo-updates is not enabled.")
176
+ }
177
+
169
178
  @Synchronized
170
179
  private fun notifyController() {
171
- if (launcher == null) {
172
- throw AssertionError("UpdatesController.notifyController was called with a null launcher, which is an error. This method should only be called when an update is ready to launch.")
180
+ controllerScope.launch {
181
+ loaderTaskFinishedMutex.withLock {
182
+ if (!loaderTaskFinishedDeferred.isCompleted) {
183
+ if (launcher == null) {
184
+ throw AssertionError("UpdatesController.notifyController was called with a null launcher, which is an error. This method should only be called when an update is ready to launch.")
185
+ }
186
+ loaderTaskFinishedDeferred.complete(Unit)
187
+ }
188
+ }
173
189
  }
174
- isLoaderTaskFinished = true
175
- (this as java.lang.Object).notify()
190
+ }
191
+
192
+ override fun shutdown() {
193
+ controllerScope.cancel()
176
194
  }
177
195
 
178
196
  companion object {
@@ -5,6 +5,7 @@ import android.content.Context
5
5
  import android.os.Bundle
6
6
  import com.facebook.react.bridge.ReactContext
7
7
  import com.facebook.react.devsupport.interfaces.DevSupportManager
8
+ import expo.modules.easclient.EASClientID
8
9
  import expo.modules.kotlin.exception.CodedException
9
10
  import expo.modules.kotlin.exception.toCodedException
10
11
  import expo.modules.updates.db.BuildData
@@ -23,14 +24,24 @@ import expo.modules.updates.procedures.CheckForUpdateProcedure
23
24
  import expo.modules.updates.procedures.FetchUpdateProcedure
24
25
  import expo.modules.updates.procedures.RelaunchProcedure
25
26
  import expo.modules.updates.procedures.StartupProcedure
27
+ import expo.modules.updates.reloadscreen.ReloadScreenManager
28
+ import expo.modules.updates.selectionpolicy.SelectionPolicy
26
29
  import expo.modules.updates.selectionpolicy.SelectionPolicyFactory
27
30
  import expo.modules.updates.statemachine.UpdatesStateMachine
28
31
  import expo.modules.updates.statemachine.UpdatesStateValue
32
+ import kotlinx.coroutines.CompletableDeferred
29
33
  import kotlinx.coroutines.CoroutineScope
30
34
  import kotlinx.coroutines.Dispatchers
35
+ import kotlinx.coroutines.cancel
31
36
  import kotlinx.coroutines.launch
37
+ import kotlinx.coroutines.runBlocking
38
+ import kotlinx.coroutines.suspendCancellableCoroutine
39
+ import kotlinx.coroutines.sync.Mutex
40
+ import kotlinx.coroutines.sync.withLock
32
41
  import java.io.File
33
42
  import java.lang.ref.WeakReference
43
+ import kotlin.coroutines.resume
44
+ import kotlin.coroutines.resumeWithException
34
45
  import kotlin.time.DurationUnit
35
46
  import kotlin.time.toDuration
36
47
 
@@ -39,7 +50,7 @@ import kotlin.time.toDuration
39
50
  */
40
51
  class EnabledUpdatesController(
41
52
  private val context: Context,
42
- private val updatesConfiguration: UpdatesConfiguration,
53
+ private var updatesConfiguration: UpdatesConfiguration,
43
54
  override val updatesDirectory: File
44
55
  ) : IUpdatesController {
45
56
  /** Keep the activity for [RelaunchProcedure] to relaunch the app. */
@@ -47,13 +58,16 @@ class EnabledUpdatesController(
47
58
  private val logger = UpdatesLogger(context.filesDir)
48
59
  override val eventManager: IUpdatesEventManager = UpdatesEventManager(logger)
49
60
 
50
- private val fileDownloader = FileDownloader(context, updatesConfiguration, logger)
51
- private val selectionPolicy = SelectionPolicyFactory.createFilterAwarePolicy(
52
- updatesConfiguration.getRuntimeVersion()
53
- )
61
+ private val selectionPolicy: SelectionPolicy
62
+ get() = SelectionPolicyFactory.createFilterAwarePolicy(updatesConfiguration.getRuntimeVersion(), updatesConfiguration)
54
63
  private val stateMachine = UpdatesStateMachine(logger, eventManager, UpdatesStateValue.entries.toSet())
55
- private val databaseHolder = DatabaseHolder(UpdatesDatabase.getInstance(context))
56
64
  private val controllerScope = CoroutineScope(Dispatchers.IO)
65
+ private val fileDownloader: FileDownloader
66
+ get() = FileDownloader(context.filesDir, EASClientID(context).uuid.toString(), updatesConfiguration, logger)
67
+ private val databaseHolder = DatabaseHolder(UpdatesDatabase.getInstance(context, Dispatchers.IO))
68
+ private val startupFinishedDeferred = CompletableDeferred<Unit>()
69
+ private val startupFinishedMutex = Mutex()
70
+ override val reloadScreenManager = ReloadScreenManager()
57
71
 
58
72
  private fun purgeUpdatesLogsOlderThanOneDay() {
59
73
  UpdatesLogReader(context.filesDir).purgeLogEntries {
@@ -70,9 +84,15 @@ class EnabledUpdatesController(
70
84
 
71
85
  @Synchronized
72
86
  private fun onStartupProcedureFinished() {
87
+ controllerScope.launch {
88
+ startupFinishedMutex.withLock {
89
+ if (!startupFinishedDeferred.isCompleted) {
90
+ startupFinishedDeferred.complete(Unit)
91
+ }
92
+ }
93
+ }
73
94
  isStartupFinished = true
74
95
  startupEndTimeMillis = System.currentTimeMillis()
75
- (this@EnabledUpdatesController as java.lang.Object).notify()
76
96
  }
77
97
 
78
98
  private val startupProcedure = StartupProcedure(
@@ -103,18 +123,14 @@ class EnabledUpdatesController(
103
123
  private val localAssetFiles
104
124
  get() = startupProcedure.localAssetFiles
105
125
 
106
- @get:Synchronized
107
126
  override val launchAssetFile: String?
108
127
  get() {
109
- while (!isStartupFinished) {
110
- try {
111
- (this as java.lang.Object).wait()
112
- } catch (e: InterruptedException) {
113
- logger.error("Interrupted while waiting for launch asset file", e, UpdatesErrorCode.InitializationError)
114
- }
128
+ runBlocking {
129
+ startupFinishedDeferred.await()
115
130
  }
116
131
  return startupProcedure.launchAssetFile
117
132
  }
133
+
118
134
  override val bundleAssetName: String?
119
135
  get() = startupProcedure.bundleAssetName
120
136
 
@@ -146,8 +162,9 @@ class EnabledUpdatesController(
146
162
 
147
163
  purgeUpdatesLogsOlderThanOneDay()
148
164
 
149
- BuildData.ensureBuildDataIsConsistent(updatesConfiguration, databaseHolder.database)
150
- databaseHolder.releaseDatabase()
165
+ if (!updatesConfiguration.hasUpdatesOverride) {
166
+ BuildData.ensureBuildDataIsConsistent(updatesConfiguration, databaseHolder.database)
167
+ }
151
168
 
152
169
  stateMachine.queueExecution(startupProcedure)
153
170
  }
@@ -165,6 +182,7 @@ class EnabledUpdatesController(
165
182
  getCurrentLauncher = { startupProcedure.launcher!! },
166
183
  setCurrentLauncher = { currentLauncher -> startupProcedure.setLauncher(currentLauncher) },
167
184
  shouldRunReaper = shouldRunReaper,
185
+ reloadScreenManager = reloadScreenManager,
168
186
  callback
169
187
  )
170
188
  stateMachine.queueExecution(procedure)
@@ -187,48 +205,47 @@ class EnabledUpdatesController(
187
205
  )
188
206
  }
189
207
 
190
- override fun relaunchReactApplicationForModule(callback: IUpdatesController.ModuleCallback<Unit>) {
208
+ override suspend fun relaunchReactApplicationForModule() = suspendCancellableCoroutine { continuation ->
191
209
  val canRelaunch = launchedUpdate != null
192
210
  if (!canRelaunch) {
193
- callback.onFailure(object : CodedException("ERR_UPDATES_RELOAD", "Cannot relaunch without a launched update.", null) {})
211
+ continuation.resumeWithException(object : CodedException("ERR_UPDATES_RELOAD", "Cannot relaunch without a launched update.", null) {})
194
212
  } else {
195
213
  relaunchReactApplication(
196
214
  shouldRunReaper = true,
197
215
  object : LauncherCallback {
198
216
  override fun onFailure(e: Exception) {
199
- callback.onFailure(e.toCodedException())
217
+ continuation.resumeWithException(e.toCodedException())
200
218
  }
201
219
 
202
220
  override fun onSuccess() {
203
- callback.onSuccess(Unit)
221
+ continuation.resume(Unit)
204
222
  }
205
223
  }
206
224
  )
207
225
  }
208
226
  }
209
227
 
210
- override fun checkForUpdate(callback: IUpdatesController.ModuleCallback<IUpdatesController.CheckForUpdateResult>) {
228
+ override suspend fun checkForUpdate() = suspendCancellableCoroutine { continuation ->
211
229
  val procedure = CheckForUpdateProcedure(context, updatesConfiguration, databaseHolder, logger, fileDownloader, selectionPolicy, launchedUpdate) {
212
- callback.onSuccess(it)
230
+ continuation.resume(it)
213
231
  }
214
232
  stateMachine.queueExecution(procedure)
215
233
  }
216
234
 
217
- override fun fetchUpdate(callback: IUpdatesController.ModuleCallback<IUpdatesController.FetchUpdateResult>) {
235
+ override suspend fun fetchUpdate() = suspendCancellableCoroutine { continuation ->
218
236
  val procedure = FetchUpdateProcedure(context, updatesConfiguration, logger, databaseHolder, updatesDirectory, fileDownloader, selectionPolicy, launchedUpdate) {
219
- callback.onSuccess(it)
237
+ continuation.resume(it)
220
238
  }
221
239
  stateMachine.queueExecution(procedure)
222
240
  }
223
241
 
224
- override fun getExtraParams(callback: IUpdatesController.ModuleCallback<Bundle>) {
242
+ override suspend fun getExtraParams() = suspendCancellableCoroutine { continuation ->
225
243
  controllerScope.launch {
226
244
  try {
227
245
  val result = ManifestMetadata.getExtraParams(
228
246
  databaseHolder.database,
229
247
  updatesConfiguration
230
248
  )
231
- databaseHolder.releaseDatabase()
232
249
  val resultMap = when (result) {
233
250
  null -> Bundle()
234
251
  else -> {
@@ -239,37 +256,51 @@ class EnabledUpdatesController(
239
256
  }
240
257
  }
241
258
  }
242
- callback.onSuccess(resultMap)
259
+ continuation.resume(resultMap)
243
260
  } catch (e: Exception) {
244
- databaseHolder.releaseDatabase()
245
- callback.onFailure(e.toCodedException())
261
+ continuation.resumeWithException(e.toCodedException())
246
262
  }
247
263
  }
248
264
  }
249
265
 
250
- override fun setExtraParam(key: String, value: String?, callback: IUpdatesController.ModuleCallback<Unit>) {
266
+ override suspend fun setExtraParam(key: String, value: String?) = suspendCancellableCoroutine { continuation ->
251
267
  controllerScope.launch {
252
- try {
268
+ runCatching {
253
269
  ManifestMetadata.setExtraParam(
254
270
  databaseHolder.database,
255
271
  updatesConfiguration,
256
272
  key,
257
273
  value
258
274
  )
259
- databaseHolder.releaseDatabase()
260
- callback.onSuccess(Unit)
261
- } catch (e: Exception) {
262
- databaseHolder.releaseDatabase()
263
- callback.onFailure(e.toCodedException())
275
+ continuation.resume(Unit)
276
+ }.onFailure { e ->
277
+ continuation.resumeWithException(e.toCodedException())
264
278
  }
265
279
  }
266
280
  }
267
281
 
282
+ override fun shutdown() {
283
+ controllerScope.cancel()
284
+ }
285
+
268
286
  override fun setUpdateURLAndRequestHeadersOverride(configOverride: UpdatesConfigurationOverride?) {
269
287
  if (!updatesConfiguration.disableAntiBrickingMeasures) {
270
288
  throw CodedException("ERR_UPDATES_RUNTIME_OVERRIDE", "Must set disableAntiBrickingMeasures configuration to use updates overriding", null)
271
289
  }
272
290
  UpdatesConfigurationOverride.save(context, configOverride)
291
+ updatesConfiguration = UpdatesConfiguration.create(context, updatesConfiguration, configOverride)
292
+ }
293
+
294
+ override fun setUpdateRequestHeadersOverride(requestHeaders: Map<String, String>?) {
295
+ val isValidRequestHeaders = UpdatesConfiguration.isValidRequestHeadersOverride(
296
+ updatesConfiguration.originalEmbeddedRequestHeaders,
297
+ requestHeaders
298
+ )
299
+ if (!isValidRequestHeaders) {
300
+ throw CodedException("ERR_UPDATES_RUNTIME_OVERRIDE", "Invalid update requestHeaders override: $requestHeaders", null)
301
+ }
302
+ val configOverride = UpdatesConfigurationOverride.saveRequestHeaders(context, requestHeaders)
303
+ updatesConfiguration = UpdatesConfiguration.create(context, updatesConfiguration, configOverride)
273
304
  }
274
305
 
275
306
  companion object {