expo-updates 1.0.0-canary-20241008-90b13ad → 1.0.0-canary-20241018-bf4b2f7-1

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 (147) hide show
  1. package/CHANGELOG.md +5 -1
  2. package/android/src/main/java/expo/modules/updates/DisabledUpdatesController.kt +12 -15
  3. package/android/src/main/java/expo/modules/updates/EnabledUpdatesController.kt +15 -17
  4. package/android/src/main/java/expo/modules/updates/IUpdatesController.kt +7 -11
  5. package/android/src/main/java/expo/modules/updates/UpdatesController.kt +8 -18
  6. package/android/src/main/java/expo/modules/updates/UpdatesDevLauncherController.kt +25 -25
  7. package/android/src/main/java/expo/modules/updates/UpdatesModule.kt +4 -28
  8. package/android/src/main/java/expo/modules/updates/UpdatesUtils.kt +5 -4
  9. package/android/src/main/java/expo/modules/updates/db/UpdatesDatabase.kt +2 -2
  10. package/android/src/main/java/expo/modules/updates/errorrecovery/ErrorRecovery.kt +4 -7
  11. package/android/src/main/java/expo/modules/updates/errorrecovery/ErrorRecoveryHandler.kt +1 -1
  12. package/android/src/main/java/expo/modules/updates/events/IUpdatesEventManager.kt +1 -7
  13. package/android/src/main/java/expo/modules/updates/events/NoOpUpdatesEventManager.kt +1 -6
  14. package/android/src/main/java/expo/modules/updates/events/UpdatesEventManager.kt +34 -0
  15. package/android/src/main/java/expo/modules/updates/launcher/DatabaseLauncher.kt +19 -24
  16. package/android/src/main/java/expo/modules/updates/launcher/NoDatabaseLauncher.kt +8 -7
  17. package/android/src/main/java/expo/modules/updates/loader/EmbeddedLoader.kt +7 -6
  18. package/android/src/main/java/expo/modules/updates/loader/FileDownloader.kt +76 -94
  19. package/android/src/main/java/expo/modules/updates/loader/Loader.kt +16 -25
  20. package/android/src/main/java/expo/modules/updates/loader/LoaderTask.kt +23 -22
  21. package/android/src/main/java/expo/modules/updates/loader/RemoteLoader.kt +13 -10
  22. package/android/src/main/java/expo/modules/updates/logging/UpdatesLogReader.kt +1 -2
  23. package/android/src/main/java/expo/modules/updates/logging/UpdatesLogger.kt +38 -29
  24. package/android/src/main/java/expo/modules/updates/manifest/EmbeddedManifestUtils.kt +1 -1
  25. package/android/src/main/java/expo/modules/updates/procedures/CheckForUpdateProcedure.kt +4 -4
  26. package/android/src/main/java/expo/modules/updates/procedures/FetchUpdateProcedure.kt +4 -0
  27. package/android/src/main/java/expo/modules/updates/procedures/RelaunchProcedure.kt +7 -4
  28. package/android/src/main/java/expo/modules/updates/procedures/StartupProcedure.kt +10 -8
  29. package/android/src/main/java/expo/modules/updates/statemachine/UpdatesStateContext.kt +61 -3
  30. package/android/src/main/java/expo/modules/updates/statemachine/UpdatesStateMachine.kt +21 -21
  31. package/build/ExpoUpdatesModule.types.d.ts +6 -9
  32. package/build/ExpoUpdatesModule.types.d.ts.map +1 -1
  33. package/build/ExpoUpdatesModule.types.js.map +1 -1
  34. package/build/Updates.d.ts +1 -18
  35. package/build/Updates.d.ts.map +1 -1
  36. package/build/Updates.js +0 -36
  37. package/build/Updates.js.map +1 -1
  38. package/build/Updates.types.d.ts +1 -0
  39. package/build/Updates.types.d.ts.map +1 -1
  40. package/build/Updates.types.js.map +1 -1
  41. package/build/UpdatesEmitter.d.ts +8 -2
  42. package/build/UpdatesEmitter.d.ts.map +1 -1
  43. package/build/UpdatesEmitter.js +42 -18
  44. package/build/UpdatesEmitter.js.map +1 -1
  45. package/build/UseUpdates.d.ts.map +1 -1
  46. package/build/UseUpdates.js +4 -13
  47. package/build/UseUpdates.js.map +1 -1
  48. package/build/UseUpdatesUtils.d.ts +1 -2
  49. package/build/UseUpdatesUtils.d.ts.map +1 -1
  50. package/build/UseUpdatesUtils.js +1 -9
  51. package/build/UseUpdatesUtils.js.map +1 -1
  52. package/build-cli/assetsVerify.d.ts +3 -0
  53. package/build-cli/assetsVerify.js +88 -0
  54. package/build-cli/assetsVerifyAsync.d.ts +59 -0
  55. package/build-cli/assetsVerifyAsync.js +127 -0
  56. package/build-cli/assetsVerifyTypes.d.ts +45 -0
  57. package/build-cli/assetsVerifyTypes.js +7 -0
  58. package/build-cli/cli.d.ts +2 -0
  59. package/build-cli/cli.js +56 -0
  60. package/build-cli/configureCodeSigning.d.ts +3 -0
  61. package/build-cli/configureCodeSigning.js +43 -0
  62. package/build-cli/configureCodeSigningAsync.d.ts +7 -0
  63. package/build-cli/configureCodeSigningAsync.js +42 -0
  64. package/build-cli/generateCodeSigning.d.ts +3 -0
  65. package/build-cli/generateCodeSigning.js +48 -0
  66. package/build-cli/generateCodeSigningAsync.d.ts +8 -0
  67. package/build-cli/generateCodeSigningAsync.js +43 -0
  68. package/build-cli/utils/args.d.ts +16 -0
  69. package/build-cli/utils/args.js +52 -0
  70. package/build-cli/utils/dir.d.ts +1 -0
  71. package/build-cli/utils/dir.js +8 -0
  72. package/build-cli/utils/log.d.ts +7 -0
  73. package/build-cli/utils/log.js +34 -0
  74. package/build-cli/utils/modifyConfigAsync.d.ts +3 -0
  75. package/build-cli/utils/modifyConfigAsync.js +41 -0
  76. package/e2e/fixtures/App.tsx +0 -14
  77. package/e2e/fixtures/Updates.e2e.ts +0 -12
  78. package/e2e/setup/project.ts +2 -2
  79. package/ios/EXUpdates/AppController.swift +29 -26
  80. package/ios/EXUpdates/AppLauncher/AppLauncher.swift +1 -1
  81. package/ios/EXUpdates/AppLauncher/AppLauncherNoDatabase.swift +0 -2
  82. package/ios/EXUpdates/AppLauncher/AppLauncherWithDatabase.swift +13 -32
  83. package/ios/EXUpdates/AppLoader/AppLoader.swift +24 -23
  84. package/ios/EXUpdates/AppLoader/AppLoaderTask.swift +13 -19
  85. package/ios/EXUpdates/AppLoader/EmbeddedAppLoader.swift +1 -9
  86. package/ios/EXUpdates/AppLoader/FileDownloader.swift +100 -217
  87. package/ios/EXUpdates/AppLoader/RemoteAppLoader.swift +16 -18
  88. package/ios/EXUpdates/AppLoader/StructuredHeaders/StringDictionary.swift +12 -1
  89. package/ios/EXUpdates/AppLoader/UpdateAsset.swift +1 -0
  90. package/ios/EXUpdates/AppLoader/UpdateResponse.swift +12 -3
  91. package/ios/EXUpdates/CodeSigning/CertificateChain.swift +10 -13
  92. package/ios/EXUpdates/CodeSigning/CodeSigningConfiguration.swift +12 -7
  93. package/ios/EXUpdates/CodeSigning/CodeSigningError.swift +32 -9
  94. package/ios/EXUpdates/Database/Migrations/UpdatesDatabaseMigration.swift +12 -1
  95. package/ios/EXUpdates/Database/Migrations/UpdatesDatabaseMigration4To5.swift +2 -0
  96. package/ios/EXUpdates/Database/Migrations/UpdatesDatabaseMigration5To6.swift +2 -0
  97. package/ios/EXUpdates/Database/Migrations/UpdatesDatabaseMigration6To7.swift +2 -0
  98. package/ios/EXUpdates/Database/Migrations/UpdatesDatabaseMigration9To10.swift +2 -0
  99. package/ios/EXUpdates/Database/UpdatesBuildData.swift +8 -8
  100. package/ios/EXUpdates/Database/UpdatesDatabase.swift +44 -25
  101. package/ios/EXUpdates/Database/UpdatesDatabaseInitialization.swift +35 -14
  102. package/ios/EXUpdates/Database/UpdatesDatabaseUtils.swift +34 -9
  103. package/ios/EXUpdates/Database/UpdatesReaper.swift +16 -11
  104. package/ios/EXUpdates/DevLauncherAppController.swift +12 -9
  105. package/ios/EXUpdates/DisabledAppController.swift +15 -15
  106. package/ios/EXUpdates/EnabledAppController.swift +15 -71
  107. package/ios/EXUpdates/ErrorRecovery.swift +22 -16
  108. package/ios/EXUpdates/Events/NoOpUpdatesEventManager.swift +8 -0
  109. package/ios/EXUpdates/Events/QueueUpdatesEventManager.swift +29 -0
  110. package/ios/EXUpdates/Events/UpdatesEventManager.swift +8 -0
  111. package/ios/EXUpdates/Exceptions.swift +2 -0
  112. package/ios/EXUpdates/Logging/UpdatesLogger.swift +15 -9
  113. package/ios/EXUpdates/Procedures/CheckForUpdateProcedure.swift +1 -0
  114. package/ios/EXUpdates/Procedures/FetchUpdateProcedure.swift +2 -0
  115. package/ios/EXUpdates/Procedures/RelaunchProcedure.swift +4 -4
  116. package/ios/EXUpdates/Procedures/StartupProcedure.swift +10 -10
  117. package/ios/EXUpdates/SelectionPolicy/ReaperSelectionPolicyDevelopmentClient.swift +1 -2
  118. package/ios/EXUpdates/SelectionPolicy/ReaperSelectionPolicyFilterAware.swift +4 -2
  119. package/ios/EXUpdates/Update/Update.swift +17 -7
  120. package/ios/EXUpdates/UpdatesConfig.swift +16 -3
  121. package/ios/EXUpdates/UpdatesError.swift +138 -0
  122. package/ios/EXUpdates/UpdatesJsEvents.swift +0 -4
  123. package/ios/EXUpdates/UpdatesModule.swift +2 -20
  124. package/ios/EXUpdates/UpdatesStateMachine.swift +49 -52
  125. package/ios/EXUpdates/UpdatesUtils.swift +2 -2
  126. package/ios/Tests/CertificateChainSpec.swift +5 -6
  127. package/ios/Tests/CodeSigningConfigurationSpec.swift +14 -0
  128. package/ios/Tests/ErrorRecoverySpec.swift +11 -9
  129. package/ios/Tests/FileDownloaderManifestParsingSpec.swift +4 -4
  130. package/ios/Tests/FileDownloaderSpec.swift +7 -2
  131. package/ios/Tests/UpdateSpec.swift +1 -1
  132. package/ios/Tests/UpdatesBuildDataSpec.swift +10 -7
  133. package/ios/Tests/UpdatesLoggerSpec.swift +1 -1
  134. package/ios/Tests/UpdatesStateMachineSpec.swift +28 -37
  135. package/package.json +11 -11
  136. package/src/ExpoUpdatesModule.types.ts +7 -11
  137. package/src/Updates.ts +0 -49
  138. package/src/Updates.types.ts +1 -0
  139. package/src/UpdatesEmitter.ts +58 -19
  140. package/src/UseUpdates.ts +4 -17
  141. package/src/UseUpdatesUtils.ts +2 -12
  142. package/android/src/main/java/expo/modules/updates/events/QueueUpdatesEventManager.kt +0 -79
  143. package/build/statemachine/UpdatesStateMachine.d.ts +0 -50
  144. package/build/statemachine/UpdatesStateMachine.d.ts.map +0 -1
  145. package/build/statemachine/UpdatesStateMachine.js +0 -116
  146. package/build/statemachine/UpdatesStateMachine.js.map +0 -1
  147. package/src/statemachine/UpdatesStateMachine.ts +0 -165
package/CHANGELOG.md CHANGED
@@ -21,6 +21,8 @@
21
21
  - Use expo-updates as source of truth for runtime version in dev client ([#31453](https://github.com/expo/expo/pull/31453) by [@wschurman](https://github.com/wschurman))
22
22
  - Fixed iOS reload crash on New Architecture mode. ([#31789](https://github.com/expo/expo/pull/31789) by [@kudo](https://github.com/kudo))
23
23
  - [cli] Disable console during runtime and fingeprint evaluation ([#31874](https://github.com/expo/expo/pull/31874) by [@wschurman](https://github.com/wschurman))
24
+ - Refactor state machine event emitting and initial state ([#31819](https://github.com/expo/expo/pull/31819) by [@wschurman](https://github.com/wschurman))
25
+ - Re-emit state on every observer observe event ([#32103](https://github.com/expo/expo/pull/32103) by [@wschurman](https://github.com/wschurman))
24
26
 
25
27
  ### 💡 Others
26
28
 
@@ -30,7 +32,9 @@
30
32
  - [Android] Use protected methods in room dao now that ksp allows it. ([#29080](https://github.com/expo/expo/pull/29080) by [@wschurman](https://github.com/wschurman))
31
33
  - Bumped Kotlin version to 1.9.24. ([#30199](https://github.com/expo/expo/pull/30199) by [@gabrieldonadel](https://github.com/gabrieldonadel))
32
34
  - Move location of assetPatternsToBeBundled config key ([#31584](https://github.com/expo/expo/pull/31584) by [@wschurman](https://github.com/wschurman))
33
- - Refactor JS event queueing and emitting ([#31818](https://github.com/expo/expo/pull/31818) by [@wschurman](https://github.com/wschurman))
35
+ - Refactor JS event queueing and emitting ([#31818](https://github.com/expo/expo/pull/31818, [#31854](https://github.com/expo/expo/pull/31854) by [@wschurman](https://github.com/wschurman))
36
+ - Remove clearUpdateCacheExperimentalAsync ([#31871](https://github.com/expo/expo/pull/31871) by [@wschurman](https://github.com/wschurman))
37
+ - Refactor errors, context injection, and error logs ([#31929](https://github.com/expo/expo/pull/31929), [#31951](https://github.com/expo/expo/pull/31951), [#31953](https://github.com/expo/expo/pull/31953), [#32009](https://github.com/expo/expo/pull/32009) by [@wschurman](https://github.com/wschurman))
34
38
 
35
39
  ### ⚠️ Notices
36
40
 
@@ -3,19 +3,17 @@ package expo.modules.updates
3
3
  import android.app.Activity
4
4
  import android.content.Context
5
5
  import android.os.Bundle
6
- import android.util.Log
7
6
  import com.facebook.react.bridge.ReactContext
8
7
  import com.facebook.react.devsupport.interfaces.DevSupportManager
9
- import expo.modules.kotlin.AppContext
10
8
  import expo.modules.kotlin.exception.CodedException
11
9
  import expo.modules.kotlin.exception.toCodedException
12
10
  import expo.modules.updates.events.IUpdatesEventManager
13
- import expo.modules.updates.events.QueueUpdatesEventManager
11
+ import expo.modules.updates.events.UpdatesEventManager
14
12
  import expo.modules.updates.launcher.Launcher
15
13
  import expo.modules.updates.launcher.NoDatabaseLauncher
14
+ import expo.modules.updates.logging.UpdatesErrorCode
16
15
  import expo.modules.updates.logging.UpdatesLogger
17
16
  import expo.modules.updates.procedures.RecreateReactContextProcedure
18
- import expo.modules.updates.statemachine.UpdatesStateContext
19
17
  import expo.modules.updates.statemachine.UpdatesStateMachine
20
18
  import expo.modules.updates.statemachine.UpdatesStateValue
21
19
  import java.io.File
@@ -34,16 +32,14 @@ class DisabledUpdatesController(
34
32
  private val context: Context,
35
33
  private val fatalException: Exception?
36
34
  ) : IUpdatesController {
37
- override var appContext: WeakReference<AppContext>? = null
38
-
39
35
  /** Keep the activity for [RecreateReactContextProcedure] to relaunch the app. */
40
36
  private var weakActivity: WeakReference<Activity>? = null
41
37
 
42
38
  private val logger = UpdatesLogger(context)
43
- override val eventManager: IUpdatesEventManager = QueueUpdatesEventManager(logger)
39
+ override val eventManager: IUpdatesEventManager = UpdatesEventManager(logger)
44
40
 
45
41
  // disabled controller state machine can only be idle or restarting
46
- private val stateMachine = UpdatesStateMachine(context, eventManager, setOf(UpdatesStateValue.Idle, UpdatesStateValue.Restarting))
42
+ private val stateMachine = UpdatesStateMachine(logger, eventManager, setOf(UpdatesStateValue.Idle, UpdatesStateValue.Restarting))
47
43
 
48
44
  private var isStarted = false
49
45
  private var startupStartTimeMillis: Long? = null
@@ -69,7 +65,7 @@ class DisabledUpdatesController(
69
65
  try {
70
66
  (this as java.lang.Object).wait()
71
67
  } catch (e: InterruptedException) {
72
- Log.e(TAG, "Interrupted while waiting for launch asset file", e)
68
+ logger.error("Interrupted while waiting for launch asset file", e, UpdatesErrorCode.InitializationError)
73
69
  }
74
70
  }
75
71
  return launcher?.launchAssetFile
@@ -78,6 +74,10 @@ class DisabledUpdatesController(
78
74
  override val bundleAssetName: String?
79
75
  get() = launcher?.bundleAssetName
80
76
 
77
+ override fun onEventListenerStartObserving() {
78
+ stateMachine.sendContextToJS()
79
+ }
80
+
81
81
  override fun onDidCreateDevSupportManager(devSupportManager: DevSupportManager) {}
82
82
 
83
83
  override fun onDidCreateReactInstance(reactContext: ReactContext) {
@@ -96,7 +96,7 @@ class DisabledUpdatesController(
96
96
  isStarted = true
97
97
  startupStartTimeMillis = System.currentTimeMillis()
98
98
 
99
- launcher = NoDatabaseLauncher(context, fatalException)
99
+ launcher = NoDatabaseLauncher(context, logger, fatalException)
100
100
 
101
101
  startupEndTimeMillis = System.currentTimeMillis()
102
102
  notifyController()
@@ -116,7 +116,8 @@ class DisabledUpdatesController(
116
116
  checkOnLaunch = UpdatesConfiguration.CheckAutomaticallyConfiguration.NEVER,
117
117
  requestHeaders = mapOf(),
118
118
  localAssetFiles = launcher?.localAssetFiles,
119
- shouldDeferToNativeForAPIMethodAvailabilityInDevelopment = false
119
+ shouldDeferToNativeForAPIMethodAvailabilityInDevelopment = false,
120
+ initialContext = stateMachine.context
120
121
  )
121
122
  }
122
123
 
@@ -137,10 +138,6 @@ class DisabledUpdatesController(
137
138
  stateMachine.queueExecution(procedure)
138
139
  }
139
140
 
140
- override fun getNativeStateMachineContext(callback: IUpdatesController.ModuleCallback<UpdatesStateContext>) {
141
- callback.onSuccess(stateMachine.context)
142
- }
143
-
144
141
  override fun checkForUpdate(
145
142
  callback: IUpdatesController.ModuleCallback<IUpdatesController.CheckForUpdateResult>
146
143
  ) {
@@ -4,19 +4,18 @@ import android.app.Activity
4
4
  import android.content.Context
5
5
  import android.os.AsyncTask
6
6
  import android.os.Bundle
7
- import android.util.Log
8
7
  import com.facebook.react.bridge.ReactContext
9
8
  import com.facebook.react.devsupport.interfaces.DevSupportManager
10
- import expo.modules.kotlin.AppContext
11
9
  import expo.modules.kotlin.exception.CodedException
12
10
  import expo.modules.kotlin.exception.toCodedException
13
11
  import expo.modules.updates.db.BuildData
14
12
  import expo.modules.updates.db.DatabaseHolder
15
13
  import expo.modules.updates.db.UpdatesDatabase
16
14
  import expo.modules.updates.events.IUpdatesEventManager
17
- import expo.modules.updates.events.QueueUpdatesEventManager
15
+ import expo.modules.updates.events.UpdatesEventManager
18
16
  import expo.modules.updates.launcher.Launcher.LauncherCallback
19
17
  import expo.modules.updates.loader.FileDownloader
18
+ import expo.modules.updates.logging.UpdatesErrorCode
20
19
  import expo.modules.updates.logging.UpdatesLogReader
21
20
  import expo.modules.updates.logging.UpdatesLogger
22
21
  import expo.modules.updates.manifest.EmbeddedManifestUtils
@@ -26,7 +25,6 @@ import expo.modules.updates.procedures.FetchUpdateProcedure
26
25
  import expo.modules.updates.procedures.RelaunchProcedure
27
26
  import expo.modules.updates.procedures.StartupProcedure
28
27
  import expo.modules.updates.selectionpolicy.SelectionPolicyFactory
29
- import expo.modules.updates.statemachine.UpdatesStateContext
30
28
  import expo.modules.updates.statemachine.UpdatesStateMachine
31
29
  import expo.modules.updates.statemachine.UpdatesStateValue
32
30
  import java.io.File
@@ -42,24 +40,22 @@ class EnabledUpdatesController(
42
40
  private val updatesConfiguration: UpdatesConfiguration,
43
41
  override val updatesDirectory: File
44
42
  ) : IUpdatesController {
45
- override var appContext: WeakReference<AppContext>? = null
46
-
47
43
  /** Keep the activity for [RelaunchProcedure] to relaunch the app. */
48
44
  private var weakActivity: WeakReference<Activity>? = null
49
45
  private val logger = UpdatesLogger(context)
50
- override val eventManager: IUpdatesEventManager = QueueUpdatesEventManager(logger)
46
+ override val eventManager: IUpdatesEventManager = UpdatesEventManager(logger)
51
47
 
52
- private val fileDownloader = FileDownloader(context, updatesConfiguration)
48
+ private val fileDownloader = FileDownloader(context, updatesConfiguration, logger)
53
49
  private val selectionPolicy = SelectionPolicyFactory.createFilterAwarePolicy(
54
50
  updatesConfiguration.getRuntimeVersion()
55
51
  )
56
- private val stateMachine = UpdatesStateMachine(context, eventManager, UpdatesStateValue.entries.toSet())
52
+ private val stateMachine = UpdatesStateMachine(logger, eventManager, UpdatesStateValue.entries.toSet())
57
53
  private val databaseHolder = DatabaseHolder(UpdatesDatabase.getInstance(context))
58
54
 
59
55
  private fun purgeUpdatesLogsOlderThanOneDay() {
60
56
  UpdatesLogReader(context).purgeLogEntries {
61
57
  if (it != null) {
62
- Log.e(TAG, "UpdatesLogReader: error in purgeLogEntries", it)
58
+ logger.error("UpdatesLogReader: error in purgeLogEntries", it, UpdatesErrorCode.Unknown)
63
59
  }
64
60
  }
65
61
  }
@@ -111,7 +107,7 @@ class EnabledUpdatesController(
111
107
  try {
112
108
  (this as java.lang.Object).wait()
113
109
  } catch (e: InterruptedException) {
114
- Log.e(TAG, "Interrupted while waiting for launch asset file", e)
110
+ logger.error("Interrupted while waiting for launch asset file", e, UpdatesErrorCode.InitializationError)
115
111
  }
116
112
  }
117
113
  return startupProcedure.launchAssetFile
@@ -119,6 +115,10 @@ class EnabledUpdatesController(
119
115
  override val bundleAssetName: String?
120
116
  get() = startupProcedure.bundleAssetName
121
117
 
118
+ override fun onEventListenerStartObserving() {
119
+ stateMachine.sendContextToJS()
120
+ }
121
+
122
122
  override fun onDidCreateDevSupportManager(devSupportManager: DevSupportManager) {
123
123
  startupProcedure.onDidCreateDevSupportManager(devSupportManager)
124
124
  }
@@ -154,6 +154,7 @@ class EnabledUpdatesController(
154
154
  context,
155
155
  weakActivity,
156
156
  updatesConfiguration,
157
+ logger,
157
158
  databaseHolder,
158
159
  updatesDirectory,
159
160
  fileDownloader,
@@ -178,7 +179,8 @@ class EnabledUpdatesController(
178
179
  checkOnLaunch = updatesConfiguration.checkOnLaunch,
179
180
  requestHeaders = updatesConfiguration.requestHeaders,
180
181
  localAssetFiles = localAssetFiles,
181
- shouldDeferToNativeForAPIMethodAvailabilityInDevelopment = false
182
+ shouldDeferToNativeForAPIMethodAvailabilityInDevelopment = false,
183
+ initialContext = stateMachine.context
182
184
  )
183
185
  }
184
186
 
@@ -202,10 +204,6 @@ class EnabledUpdatesController(
202
204
  }
203
205
  }
204
206
 
205
- override fun getNativeStateMachineContext(callback: IUpdatesController.ModuleCallback<UpdatesStateContext>) {
206
- callback.onSuccess(stateMachine.context)
207
- }
208
-
209
207
  override fun checkForUpdate(callback: IUpdatesController.ModuleCallback<IUpdatesController.CheckForUpdateResult>) {
210
208
  val procedure = CheckForUpdateProcedure(context, updatesConfiguration, databaseHolder, logger, fileDownloader, selectionPolicy, launchedUpdate) {
211
209
  callback.onSuccess(it)
@@ -214,7 +212,7 @@ class EnabledUpdatesController(
214
212
  }
215
213
 
216
214
  override fun fetchUpdate(callback: IUpdatesController.ModuleCallback<IUpdatesController.FetchUpdateResult>) {
217
- val procedure = FetchUpdateProcedure(context, updatesConfiguration, databaseHolder, updatesDirectory, fileDownloader, selectionPolicy, launchedUpdate) {
215
+ val procedure = FetchUpdateProcedure(context, updatesConfiguration, logger, databaseHolder, updatesDirectory, fileDownloader, selectionPolicy, launchedUpdate) {
218
216
  callback.onSuccess(it)
219
217
  }
220
218
  stateMachine.queueExecution(procedure)
@@ -3,7 +3,6 @@ package expo.modules.updates
3
3
  import android.os.Bundle
4
4
  import com.facebook.react.bridge.ReactContext
5
5
  import com.facebook.react.devsupport.interfaces.DevSupportManager
6
- import expo.modules.kotlin.AppContext
7
6
  import expo.modules.kotlin.exception.CodedException
8
7
  import expo.modules.updates.db.entity.AssetEntity
9
8
  import expo.modules.updates.db.entity.UpdateEntity
@@ -12,7 +11,6 @@ import expo.modules.updates.loader.LoaderTask
12
11
  import expo.modules.updates.manifest.Update
13
12
  import expo.modules.updates.statemachine.UpdatesStateContext
14
13
  import java.io.File
15
- import java.lang.ref.WeakReference
16
14
  import java.util.Date
17
15
  import kotlin.time.Duration
18
16
  import kotlin.time.DurationUnit
@@ -42,13 +40,10 @@ interface IUpdatesController {
42
40
  */
43
41
  val updatesDirectory: File?
44
42
 
45
- /**
46
- * The [AppContext] assigned from [UpdatesModule]
47
- */
48
- var appContext: WeakReference<AppContext>?
49
-
50
43
  val eventManager: IUpdatesEventManager
51
44
 
45
+ fun onEventListenerStartObserving()
46
+
52
47
  fun onDidCreateDevSupportManager(devSupportManager: DevSupportManager)
53
48
 
54
49
  fun onDidCreateReactInstance(reactContext: ReactContext)
@@ -99,7 +94,9 @@ interface IUpdatesController {
99
94
  * or a Dev Client, which have their own controller/JS API implementations, we want the JS API
100
95
  * calls to go through.
101
96
  */
102
- val shouldDeferToNativeForAPIMethodAvailabilityInDevelopment: Boolean
97
+ val shouldDeferToNativeForAPIMethodAvailabilityInDevelopment: Boolean,
98
+
99
+ val initialContext: UpdatesStateContext
103
100
  ) {
104
101
  fun toModuleConstantsMap(): Map<String, Any?> = mutableMapOf<String, Any?>().apply {
105
102
  this["isEmergencyLaunch"] = emergencyLaunchException != null
@@ -112,6 +109,7 @@ interface IUpdatesController {
112
109
  this["checkAutomatically"] = checkOnLaunch.toJSString()
113
110
  this["channel"] = requestHeaders["expo-channel-name"] ?: ""
114
111
  this["shouldDeferToNativeForAPIMethodAvailabilityInDevelopment"] = shouldDeferToNativeForAPIMethodAvailabilityInDevelopment || BuildConfig.EX_UPDATES_NATIVE_DEBUG
112
+ this["initialContext"] = initialContext.bundle
115
113
 
116
114
  if (launchedUpdate != null) {
117
115
  this["updateId"] = launchedUpdate.id.toString()
@@ -134,8 +132,6 @@ interface IUpdatesController {
134
132
 
135
133
  fun relaunchReactApplicationForModule(callback: ModuleCallback<Unit>)
136
134
 
137
- fun getNativeStateMachineContext(callback: ModuleCallback<UpdatesStateContext>)
138
-
139
135
  sealed class CheckForUpdateResult(private val status: Status) {
140
136
  private enum class Status {
141
137
  NO_UPDATE_AVAILABLE,
@@ -147,7 +143,7 @@ interface IUpdatesController {
147
143
  class NoUpdateAvailable(val reason: LoaderTask.RemoteCheckResultNotAvailableReason) : CheckForUpdateResult(Status.NO_UPDATE_AVAILABLE)
148
144
  class UpdateAvailable(val update: Update) : CheckForUpdateResult(Status.UPDATE_AVAILABLE)
149
145
  class RollBackToEmbedded(val commitTime: Date) : CheckForUpdateResult(Status.ROLL_BACK_TO_EMBEDDED)
150
- class ErrorResult(val error: Exception, val message: String) : CheckForUpdateResult(Status.ERROR)
146
+ class ErrorResult(val error: Exception) : CheckForUpdateResult(Status.ERROR)
151
147
  }
152
148
  fun checkForUpdate(callback: ModuleCallback<CheckForUpdateResult>)
153
149
 
@@ -2,7 +2,6 @@ package expo.modules.updates
2
2
 
3
3
  import android.content.Context
4
4
  import com.facebook.react.ReactApplication
5
- import expo.modules.kotlin.AppContext
6
5
  import expo.modules.kotlin.events.EventEmitter
7
6
  import expo.modules.updates.loader.LoaderTask
8
7
  import expo.modules.updates.logging.UpdatesErrorCode
@@ -51,7 +50,8 @@ class UpdatesController {
51
50
  UpdatesUtils.getOrCreateUpdatesDirectory(context)
52
51
  } catch (e: Exception) {
53
52
  logger.error(
54
- "The expo-updates system is disabled due to a storage access error: ${e.message}",
53
+ "The expo-updates system is disabled due to a storage access error",
54
+ e,
55
55
  UpdatesErrorCode.InitializationError
56
56
  )
57
57
  singletonInstance = DisabledUpdatesController(context, e)
@@ -151,23 +151,13 @@ class UpdatesController {
151
151
  }
152
152
  }
153
153
 
154
- /**
155
- * For [UpdatesModule] to set the [shouldEmitJsEvents] property.
156
- */
157
- internal var shouldEmitJsEvents: Boolean
158
- get() = singletonInstance?.eventManager?.shouldEmitJsEvents ?: false
159
- set(value) {
160
- singletonInstance?.eventManager?.shouldEmitJsEvents = value
161
- }
154
+ internal fun onEventListenerStartObserving(eventEmitter: EventEmitter?) {
155
+ singletonInstance?.eventManager?.eventEmitter = eventEmitter
156
+ singletonInstance?.onEventListenerStartObserving()
157
+ }
162
158
 
163
- /**
164
- * Binds the [AppContext] and [EventEmitter] instance from [UpdatesModule].
165
- */
166
- internal fun bindAppContext(appContext: WeakReference<AppContext>, eventEmitter: EventEmitter?) {
167
- singletonInstance?.let {
168
- it.appContext = appContext
169
- it.eventManager.eventEmitter = eventEmitter
170
- }
159
+ internal fun onEventListenerStopObserving() {
160
+ singletonInstance?.eventManager?.eventEmitter = null
171
161
  }
172
162
  }
173
163
  }
@@ -3,11 +3,9 @@ package expo.modules.updates
3
3
  import android.content.Context
4
4
  import android.os.AsyncTask
5
5
  import android.os.Bundle
6
- import android.util.Log
7
6
  import android.net.Uri
8
7
  import com.facebook.react.bridge.ReactContext
9
8
  import com.facebook.react.devsupport.interfaces.DevSupportManager
10
- import expo.modules.kotlin.AppContext
11
9
  import expo.modules.kotlin.exception.CodedException
12
10
  import expo.modules.updates.db.DatabaseHolder
13
11
  import expo.modules.updates.db.Reaper
@@ -22,6 +20,8 @@ import expo.modules.updates.loader.Loader
22
20
  import expo.modules.updates.loader.RemoteLoader
23
21
  import expo.modules.updates.loader.UpdateDirective
24
22
  import expo.modules.updates.loader.UpdateResponse
23
+ import expo.modules.updates.logging.UpdatesErrorCode
24
+ import expo.modules.updates.logging.UpdatesLogger
25
25
  import expo.modules.updates.selectionpolicy.LauncherSelectionPolicySingleUpdate
26
26
  import expo.modules.updates.selectionpolicy.ReaperSelectionPolicyDevelopmentClient
27
27
  import expo.modules.updates.selectionpolicy.SelectionPolicy
@@ -49,12 +49,13 @@ class UpdatesDevLauncherController(
49
49
  override val updatesDirectory: File?,
50
50
  private val updatesDirectoryException: Exception?
51
51
  ) : IUpdatesController, UpdatesInterface {
52
- override var appContext: WeakReference<AppContext>? = null
53
52
  override val eventManager = NoOpUpdatesEventManager()
54
53
  override var updatesInterfaceCallbacks: WeakReference<UpdatesInterfaceCallbacks>? = null
55
54
 
56
55
  private var launcher: Launcher? = null
57
56
 
57
+ private val logger = UpdatesLogger(context)
58
+
58
59
  private var previousUpdatesConfiguration: UpdatesConfiguration? = null
59
60
  private var updatesConfiguration: UpdatesConfiguration? = initialUpdatesConfiguration
60
61
 
@@ -83,6 +84,10 @@ class UpdatesDevLauncherController(
83
84
  override val bundleAssetName: String
84
85
  get() = throw Exception("IUpdatesController.bundleAssetName should not be called in dev client")
85
86
 
87
+ override fun onEventListenerStartObserving() {
88
+ // no-op for UpdatesDevLauncherController
89
+ }
90
+
86
91
  override fun onDidCreateDevSupportManager(devSupportManager: DevSupportManager) {}
87
92
 
88
93
  override fun onDidCreateReactInstance(reactContext: ReactContext) {}
@@ -108,13 +113,11 @@ class UpdatesDevLauncherController(
108
113
  launcher = null
109
114
  }
110
115
 
111
- override fun getRuntimeVersion(context: Context): String? {
112
- return updatesConfiguration?.getRuntimeVersion()
113
- }
116
+ override val runtimeVersion: String?
117
+ get() = updatesConfiguration?.getRuntimeVersion()
114
118
 
115
- override fun getUpdateUrl(context: Context): Uri? {
116
- return updatesConfiguration?.updateUrl
117
- }
119
+ override val updateUrl: Uri?
120
+ get() = updatesConfiguration?.updateUrl
118
121
 
119
122
  /**
120
123
  * Fetch an update using a dynamically generated configuration object (including a potentially
@@ -122,12 +125,11 @@ class UpdatesDevLauncherController(
122
125
  */
123
126
  override fun fetchUpdateWithConfiguration(
124
127
  configuration: HashMap<String, Any>,
125
- context: Context,
126
128
  callback: UpdatesInterface.UpdateCallback
127
129
  ) {
128
130
  val newUpdatesConfiguration: UpdatesConfiguration
129
131
  try {
130
- newUpdatesConfiguration = createUpdatesConfiguration(configuration, context)
132
+ newUpdatesConfiguration = createUpdatesConfiguration(configuration)
131
133
  } catch (e: Exception) {
132
134
  callback.onFailure(e)
133
135
  return
@@ -140,10 +142,11 @@ class UpdatesDevLauncherController(
140
142
 
141
143
  setDevelopmentSelectionPolicy()
142
144
 
143
- val fileDownloader = FileDownloader(context, updatesConfiguration!!)
145
+ val fileDownloader = FileDownloader(context, updatesConfiguration!!, logger)
144
146
  val loader = RemoteLoader(
145
147
  context,
146
148
  updatesConfiguration!!,
149
+ logger,
147
150
  databaseHolder.database,
148
151
  fileDownloader,
149
152
  updatesDirectory,
@@ -164,7 +167,7 @@ class UpdatesDevLauncherController(
164
167
  callback.onSuccess(null)
165
168
  return
166
169
  }
167
- launchUpdate(loaderResult.updateEntity, updatesConfiguration!!, fileDownloader, context, callback)
170
+ launchUpdate(loaderResult.updateEntity, updatesConfiguration!!, fileDownloader, callback)
168
171
  }
169
172
 
170
173
  override fun onAssetLoaded(
@@ -193,18 +196,18 @@ class UpdatesDevLauncherController(
193
196
  })
194
197
  }
195
198
 
196
- override fun isValidUpdatesConfiguration(configuration: HashMap<String, Any>, context: Context): Boolean {
199
+ override fun isValidUpdatesConfiguration(configuration: HashMap<String, Any>): Boolean {
197
200
  return try {
198
- createUpdatesConfiguration(configuration, context)
201
+ createUpdatesConfiguration(configuration)
199
202
  true
200
203
  } catch (e: Exception) {
201
- Log.e(TAG, "Invalid updates configuration: ${e.localizedMessage}")
204
+ logger.error("Invalid updates configuration", e, UpdatesErrorCode.InitializationError)
202
205
  false
203
206
  }
204
207
  }
205
208
 
206
209
  @Throws(Exception::class)
207
- private fun createUpdatesConfiguration(configuration: HashMap<String, Any>, context: Context): UpdatesConfiguration {
210
+ private fun createUpdatesConfiguration(configuration: HashMap<String, Any>): UpdatesConfiguration {
208
211
  if (updatesDirectory == null) {
209
212
  throw updatesDirectoryException!!
210
213
  }
@@ -240,7 +243,6 @@ class UpdatesDevLauncherController(
240
243
  update: UpdateEntity,
241
244
  configuration: UpdatesConfiguration,
242
245
  fileDownloader: FileDownloader,
243
- context: Context,
244
246
  callback: UpdatesInterface.UpdateCallback
245
247
  ) {
246
248
  // ensure that we launch the update we want, even if it isn't the latest one
@@ -258,14 +260,15 @@ class UpdatesDevLauncherController(
258
260
  )
259
261
 
260
262
  val launcher = DatabaseLauncher(
263
+ context,
261
264
  configuration,
262
265
  updatesDirectory!!,
263
266
  fileDownloader,
264
- selectionPolicy
267
+ selectionPolicy,
268
+ logger
265
269
  )
266
270
  launcher.launch(
267
271
  databaseHolder.database,
268
- context,
269
272
  object : Launcher.LauncherCallback {
270
273
  override fun onFailure(e: Exception) {
271
274
  databaseHolder.releaseDatabase()
@@ -324,7 +327,8 @@ class UpdatesDevLauncherController(
324
327
  checkOnLaunch = updatesConfiguration?.checkOnLaunch ?: UpdatesConfiguration.CheckAutomaticallyConfiguration.ALWAYS,
325
328
  requestHeaders = updatesConfiguration?.requestHeaders ?: mapOf(),
326
329
  localAssetFiles = localAssetFiles,
327
- shouldDeferToNativeForAPIMethodAvailabilityInDevelopment = true
330
+ shouldDeferToNativeForAPIMethodAvailabilityInDevelopment = true,
331
+ initialContext = UpdatesStateContext()
328
332
  )
329
333
  }
330
334
 
@@ -335,10 +339,6 @@ class UpdatesDevLauncherController(
335
339
  callback.onSuccess(Unit)
336
340
  }
337
341
 
338
- override fun getNativeStateMachineContext(callback: IUpdatesController.ModuleCallback<UpdatesStateContext>) {
339
- callback.onSuccess(UpdatesStateContext())
340
- }
341
-
342
342
  override fun checkForUpdate(
343
343
  callback: IUpdatesController.ModuleCallback<IUpdatesController.CheckForUpdateResult>
344
344
  ) {
@@ -3,7 +3,6 @@ package expo.modules.updates
3
3
  import android.content.Context
4
4
  import android.os.AsyncTask
5
5
  import android.os.Bundle
6
- import android.util.Log
7
6
  import expo.modules.kotlin.Promise
8
7
  import expo.modules.kotlin.exception.CodedException
9
8
  import expo.modules.kotlin.exception.Exceptions
@@ -14,8 +13,6 @@ import expo.modules.updates.logging.UpdatesErrorCode
14
13
  import expo.modules.updates.logging.UpdatesLogEntry
15
14
  import expo.modules.updates.logging.UpdatesLogReader
16
15
  import expo.modules.updates.logging.UpdatesLogger
17
- import expo.modules.updates.statemachine.UpdatesStateContext
18
- import java.lang.ref.WeakReference
19
16
  import java.util.Date
20
17
 
21
18
  /**
@@ -42,19 +39,12 @@ class UpdatesModule : Module() {
42
39
  UpdatesController.instance.getConstantsForModule().toModuleConstantsMap()
43
40
  }
44
41
 
45
- OnCreate {
46
- UpdatesController.bindAppContext(
47
- WeakReference(appContext),
48
- appContext.eventEmitter(this@UpdatesModule)
49
- )
50
- }
51
-
52
42
  OnStartObserving {
53
- UpdatesController.shouldEmitJsEvents = true
43
+ UpdatesController.onEventListenerStartObserving(appContext.eventEmitter(this@UpdatesModule))
54
44
  }
55
45
 
56
46
  OnStopObserving {
57
- UpdatesController.shouldEmitJsEvents = false
47
+ UpdatesController.onEventListenerStopObserving()
58
48
  }
59
49
 
60
50
  AsyncFunction("reload") { promise: Promise ->
@@ -71,27 +61,13 @@ class UpdatesModule : Module() {
71
61
  )
72
62
  }
73
63
 
74
- // Used internally by useUpdates() to get its initial state
75
- AsyncFunction("getNativeStateMachineContextAsync") { promise: Promise ->
76
- UpdatesController.instance.getNativeStateMachineContext(object : IUpdatesController.ModuleCallback<UpdatesStateContext> {
77
- override fun onSuccess(result: UpdatesStateContext) {
78
- promise.resolve(result.bundle)
79
- }
80
-
81
- override fun onFailure(exception: CodedException) {
82
- promise.reject(exception)
83
- }
84
- })
85
- }
86
-
87
64
  AsyncFunction("checkForUpdateAsync") { promise: Promise ->
88
65
  UpdatesController.instance.checkForUpdate(
89
66
  object : IUpdatesController.ModuleCallback<IUpdatesController.CheckForUpdateResult> {
90
67
  override fun onSuccess(result: IUpdatesController.CheckForUpdateResult) {
91
68
  when (result) {
92
69
  is IUpdatesController.CheckForUpdateResult.ErrorResult -> {
93
- promise.reject("ERR_UPDATES_CHECK", result.message, result.error)
94
- Log.e(TAG, result.message, result.error)
70
+ promise.reject("ERR_UPDATES_CHECK", "Failed to check for update", result.error)
95
71
  }
96
72
  is IUpdatesController.CheckForUpdateResult.NoUpdateAvailable -> {
97
73
  promise.resolve(
@@ -256,7 +232,7 @@ class UpdatesModule : Module() {
256
232
  }
257
233
  }
258
234
 
259
- internal fun clearLogEntries(context: Context, completionHandler: (_: Error?) -> Unit) {
235
+ internal fun clearLogEntries(context: Context, completionHandler: (_: Exception?) -> Unit) {
260
236
  val reader = UpdatesLogReader(context)
261
237
  reader.purgeLogEntries(
262
238
  olderThan = Date(),
@@ -6,6 +6,8 @@ import android.util.Base64
6
6
  import android.util.Log
7
7
  import expo.modules.updates.UpdatesConfiguration.CheckAutomaticallyConfiguration
8
8
  import expo.modules.updates.db.entity.AssetEntity
9
+ import expo.modules.updates.logging.UpdatesErrorCode
10
+ import expo.modules.updates.logging.UpdatesLogger
9
11
  import org.apache.commons.io.FileUtils
10
12
  import org.json.JSONArray
11
13
  import org.json.JSONObject
@@ -154,6 +156,7 @@ object UpdatesUtils {
154
156
 
155
157
  fun shouldCheckForUpdateOnLaunch(
156
158
  updatesConfiguration: UpdatesConfiguration,
159
+ logger: UpdatesLogger,
157
160
  context: Context
158
161
  ): Boolean {
159
162
  return when (updatesConfiguration.checkOnLaunch) {
@@ -163,10 +166,8 @@ object UpdatesUtils {
163
166
  CheckAutomaticallyConfiguration.WIFI_ONLY -> {
164
167
  val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager?
165
168
  if (cm == null) {
166
- Log.e(
167
- TAG,
168
- "Could not determine active network connection is metered; not checking for updates"
169
- )
169
+ val cause = Exception("Null ConnectivityManager system service")
170
+ logger.error("Could not determine active network connection is metered; not checking for updates", cause, UpdatesErrorCode.Unknown)
170
171
  return false
171
172
  }
172
173
  !cm.isActiveNetworkMetered
@@ -58,9 +58,9 @@ abstract class UpdatesDatabase : RoomDatabase() {
58
58
  private const val DB_NAME = "updates.db"
59
59
 
60
60
  @JvmStatic @Synchronized
61
- fun getInstance(context: Context?): UpdatesDatabase {
61
+ fun getInstance(context: Context): UpdatesDatabase {
62
62
  if (instance == null) {
63
- instance = Room.databaseBuilder(context!!, UpdatesDatabase::class.java, DB_NAME)
63
+ instance = Room.databaseBuilder(context, UpdatesDatabase::class.java, DB_NAME)
64
64
  .addMigrations(MIGRATION_4_5)
65
65
  .addMigrations(MIGRATION_5_6)
66
66
  .addMigrations(MIGRATION_6_7)