expo-updates 0.24.3 → 0.24.4

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 (50) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/android/build.gradle +2 -2
  3. package/android/src/main/java/expo/modules/updates/DisabledUpdatesController.kt +47 -8
  4. package/android/src/main/java/expo/modules/updates/EnabledUpdatesController.kt +7 -7
  5. package/android/src/main/java/expo/modules/updates/IUpdatesController.kt +9 -0
  6. package/android/src/main/java/expo/modules/updates/UpdatesConfiguration.kt +4 -3
  7. package/android/src/main/java/expo/modules/updates/UpdatesController.kt +5 -2
  8. package/android/src/main/java/expo/modules/updates/UpdatesDevLauncherController.kt +8 -3
  9. package/android/src/main/java/expo/modules/updates/UpdatesModule.kt +5 -7
  10. package/android/src/main/java/expo/modules/updates/UpdatesPackage.kt +2 -3
  11. package/android/src/main/java/expo/modules/updates/UpdatesUtils.kt +3 -1
  12. package/android/src/main/java/expo/modules/updates/codesigning/CertificateChain.kt +3 -1
  13. package/android/src/main/java/expo/modules/updates/codesigning/CodeSigningConfiguration.kt +1 -1
  14. package/android/src/main/java/expo/modules/updates/codesigning/SignatureHeaderInfo.kt +9 -3
  15. package/android/src/main/java/expo/modules/updates/db/BuildData.kt +2 -2
  16. package/android/src/main/java/expo/modules/updates/db/dao/AssetDao.kt +3 -1
  17. package/android/src/main/java/expo/modules/updates/db/dao/JSONDataDao.kt +3 -1
  18. package/android/src/main/java/expo/modules/updates/db/entity/UpdateEntity.kt +1 -1
  19. package/android/src/main/java/expo/modules/updates/db/enums/UpdateStatus.kt +3 -0
  20. package/android/src/main/java/expo/modules/updates/loader/EmbeddedLoader.kt +5 -1
  21. package/android/src/main/java/expo/modules/updates/loader/FileDownloader.kt +4 -4
  22. package/android/src/main/java/expo/modules/updates/loader/LegacySignatureUtils.kt +3 -1
  23. package/android/src/main/java/expo/modules/updates/loader/Loader.kt +20 -9
  24. package/android/src/main/java/expo/modules/updates/loader/LoaderTask.kt +10 -3
  25. package/android/src/main/java/expo/modules/updates/logging/UpdatesLogEntry.kt +1 -1
  26. package/android/src/main/java/expo/modules/updates/manifest/LegacyUpdateManifest.kt +8 -4
  27. package/android/src/main/java/expo/modules/updates/manifest/ResponseHeaderData.kt +1 -1
  28. package/android/src/main/java/expo/modules/updates/procedures/RecreateReactContextProcedure.kt +30 -0
  29. package/android/src/main/java/expo/modules/updates/procedures/RelaunchProcedure.kt +1 -1
  30. package/android/src/main/java/expo/modules/updates/procedures/StartupProcedure.kt +11 -4
  31. package/android/src/main/java/expo/modules/updates/selectionpolicy/LoaderSelectionPolicyFilterAware.kt +6 -2
  32. package/android/src/main/java/expo/modules/updates/statemachine/UpdatesStateContext.kt +1 -1
  33. package/android/src/main/java/expo/modules/updates/statemachine/UpdatesStateMachine.kt +2 -2
  34. package/build/Updates.d.ts.map +1 -1
  35. package/build/Updates.js +19 -11
  36. package/build/Updates.js.map +1 -1
  37. package/e2e/README.md +2 -2
  38. package/e2e/fixtures/App-updates-disabled.tsx +22 -0
  39. package/e2e/fixtures/Updates-dev-client.e2e.ts +77 -0
  40. package/e2e/fixtures/Updates-disabled.e2e.ts +38 -0
  41. package/e2e/setup/create-dev-client-eas-project.ts +41 -0
  42. package/e2e/setup/project.ts +75 -36
  43. package/ios/EXUpdates/AppController.swift +15 -1
  44. package/ios/EXUpdates/DevLauncherAppController.swift +7 -3
  45. package/ios/EXUpdates/DisabledAppController.swift +16 -4
  46. package/ios/EXUpdates/EnabledAppController.swift +2 -1
  47. package/ios/EXUpdates/Procedures/RecreateReactContextProcedure.swift +31 -0
  48. package/ios/EXUpdates/UpdatesModule.swift +5 -6
  49. package/package.json +2 -2
  50. package/src/Updates.ts +30 -11
package/CHANGELOG.md CHANGED
@@ -10,6 +10,12 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 0.24.4 — 2023-12-19
14
+
15
+ ### 🐛 Bug fixes
16
+
17
+ - Add relaunch to disabled and dev client controllers. ([#25973](https://github.com/expo/expo/pull/25973) by [@wschurman](https://github.com/wschurman))
18
+
13
19
  ## 0.24.3 — 2023-12-15
14
20
 
15
21
  _This version does not introduce any user-facing changes._
@@ -4,7 +4,7 @@ apply plugin: 'kotlin-kapt'
4
4
  apply plugin: 'maven-publish'
5
5
 
6
6
  group = 'host.exp.exponent'
7
- version = '0.24.3'
7
+ version = '0.24.4'
8
8
 
9
9
  def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
10
10
  if (expoModulesCorePlugin.exists()) {
@@ -122,7 +122,7 @@ android {
122
122
  namespace "expo.modules.updates"
123
123
  defaultConfig {
124
124
  versionCode 31
125
- versionName '0.24.3'
125
+ versionName '0.24.4'
126
126
  consumerProguardFiles("proguard-rules.pro")
127
127
  testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
128
128
 
@@ -1,20 +1,27 @@
1
+ @file:Suppress("UnusedImport") // this needs to stay for versioning to work
2
+
1
3
  package expo.modules.updates
2
4
 
3
5
  import android.content.Context
4
6
  import android.os.Bundle
5
7
  import android.util.Log
8
+ import com.facebook.react.ReactApplication
6
9
  import com.facebook.react.ReactInstanceManager
10
+ import com.facebook.react.ReactNativeHost
11
+ import com.facebook.react.bridge.WritableMap
7
12
  import expo.modules.kotlin.exception.CodedException
13
+ import expo.modules.kotlin.exception.toCodedException
8
14
  import expo.modules.updates.UpdatesConfiguration.Companion.UPDATES_CONFIGURATION_RELEASE_CHANNEL_DEFAULT_VALUE
9
15
  import expo.modules.updates.launcher.Launcher
10
16
  import expo.modules.updates.launcher.NoDatabaseLauncher
17
+ import expo.modules.updates.logging.UpdatesLogger
18
+ import expo.modules.updates.procedures.RecreateReactContextProcedure
19
+ import expo.modules.updates.statemachine.UpdatesStateChangeEventSender
11
20
  import expo.modules.updates.statemachine.UpdatesStateContext
21
+ import expo.modules.updates.statemachine.UpdatesStateEventType
22
+ import expo.modules.updates.statemachine.UpdatesStateMachine
12
23
  import java.io.File
13
-
14
- // this needs to stay for versioning to work
15
- /* ktlint-disable no-unused-imports */
16
- import expo.modules.updates.UpdatesConfiguration
17
- /* ktlint-enable no-unused-imports */
24
+ import java.lang.ref.WeakReference
18
25
 
19
26
  /**
20
27
  * Updates controller for applications that either disable updates explicitly or have an error
@@ -27,7 +34,15 @@ class DisabledUpdatesController(
27
34
  private val context: Context,
28
35
  private val fatalException: Exception?,
29
36
  private val isMissingRuntimeVersion: Boolean
30
- ) : IUpdatesController {
37
+ ) : IUpdatesController, UpdatesStateChangeEventSender {
38
+ private val reactNativeHost: WeakReference<ReactNativeHost>? = if (context is ReactApplication) {
39
+ WeakReference(context.reactNativeHost)
40
+ } else {
41
+ null
42
+ }
43
+ private val logger = UpdatesLogger(context)
44
+ private val stateMachine = UpdatesStateMachine(context, this)
45
+
31
46
  private var isStarted = false
32
47
  private var launcher: Launcher? = null
33
48
  private var isLoaderTaskFinished = false
@@ -82,15 +97,28 @@ class DisabledUpdatesController(
82
97
  requestHeaders = mapOf(),
83
98
  localAssetFiles = launcher?.localAssetFiles,
84
99
  isMissingRuntimeVersion = isMissingRuntimeVersion,
100
+ shouldDeferToNativeForAPIMethodAvailabilityInDevelopment = false
85
101
  )
86
102
  }
87
103
 
88
104
  override fun relaunchReactApplicationForModule(callback: IUpdatesController.ModuleCallback<Unit>) {
89
- callback.onFailure(UpdatesDisabledException("You cannot reload when expo-updates is not enabled."))
105
+ val procedure = RecreateReactContextProcedure(
106
+ reactNativeHost,
107
+ object : Launcher.LauncherCallback {
108
+ override fun onFailure(e: Exception) {
109
+ callback.onFailure(e.toCodedException())
110
+ }
111
+
112
+ override fun onSuccess() {
113
+ callback.onSuccess(Unit)
114
+ }
115
+ }
116
+ )
117
+ stateMachine.queueExecution(procedure)
90
118
  }
91
119
 
92
120
  override fun getNativeStateMachineContext(callback: IUpdatesController.ModuleCallback<UpdatesStateContext>) {
93
- callback.onFailure(UpdatesDisabledException("You cannot check for updates when expo-updates is not enabled."))
121
+ callback.onSuccess(stateMachine.context)
94
122
  }
95
123
 
96
124
  override fun checkForUpdate(
@@ -129,4 +157,15 @@ class DisabledUpdatesController(
129
157
  companion object {
130
158
  private val TAG = DisabledUpdatesController::class.java.simpleName
131
159
  }
160
+
161
+ override fun sendUpdateStateChangeEventToBridge(
162
+ eventType: UpdatesStateEventType,
163
+ context: UpdatesStateContext
164
+ ) {
165
+ sendEventToJS(EnabledUpdatesController.UPDATES_STATE_CHANGE_EVENT_NAME, eventType.type, context.writableMap)
166
+ }
167
+
168
+ private fun sendEventToJS(eventName: String, eventType: String, params: WritableMap?) {
169
+ UpdatesUtils.sendEventToReactNative(reactNativeHost, logger, eventName, eventType, params)
170
+ }
132
171
  }
@@ -1,3 +1,5 @@
1
+ @file:Suppress("UnusedImport") // this needs to stay for versioning to work
2
+
1
3
  package expo.modules.updates
2
4
 
3
5
  import android.content.Context
@@ -33,9 +35,6 @@ import java.io.File
33
35
  import java.lang.ref.WeakReference
34
36
 
35
37
  // this needs to stay for versioning to work
36
- /* ktlint-disable no-unused-imports */
37
- import expo.modules.updates.UpdatesConfiguration
38
- /* ktlint-enable no-unused-imports */
39
38
 
40
39
  /**
41
40
  * Updates controller for applications that have updates enabled and properly-configured.
@@ -45,7 +44,7 @@ class EnabledUpdatesController(
45
44
  private val updatesConfiguration: UpdatesConfiguration,
46
45
  override val updatesDirectory: File
47
46
  ) : IUpdatesController, UpdatesStateChangeEventSender {
48
- private var reactNativeHost: WeakReference<ReactNativeHost>? = if (context is ReactApplication) {
47
+ private val reactNativeHost: WeakReference<ReactNativeHost>? = if (context is ReactApplication) {
49
48
  WeakReference(context.reactNativeHost)
50
49
  } else {
51
50
  null
@@ -198,6 +197,7 @@ class EnabledUpdatesController(
198
197
  requestHeaders = updatesConfiguration.requestHeaders,
199
198
  localAssetFiles = localAssetFiles,
200
199
  isMissingRuntimeVersion = false,
200
+ shouldDeferToNativeForAPIMethodAvailabilityInDevelopment = false
201
201
  )
202
202
  }
203
203
 
@@ -244,7 +244,7 @@ class EnabledUpdatesController(
244
244
  try {
245
245
  val result = ManifestMetadata.getExtraParams(
246
246
  databaseHolder.database,
247
- updatesConfiguration,
247
+ updatesConfiguration
248
248
  )
249
249
  databaseHolder.releaseDatabase()
250
250
  val resultMap = when (result) {
@@ -290,7 +290,7 @@ class EnabledUpdatesController(
290
290
  private const val UPDATE_NO_UPDATE_AVAILABLE_EVENT = "noUpdateAvailable"
291
291
  private const val UPDATE_ERROR_EVENT = "error"
292
292
 
293
- private const val UPDATES_EVENT_NAME = "Expo.nativeUpdatesEvent"
294
- private const val UPDATES_STATE_CHANGE_EVENT_NAME = "Expo.nativeUpdatesStateChangeEvent"
293
+ const val UPDATES_EVENT_NAME = "Expo.nativeUpdatesEvent"
294
+ const val UPDATES_STATE_CHANGE_EVENT_NAME = "Expo.nativeUpdatesStateChangeEvent"
295
295
  }
296
296
  }
@@ -78,6 +78,15 @@ interface IUpdatesController {
78
78
  * updates will be disabled and a warning will be logged.
79
79
  */
80
80
  val isMissingRuntimeVersion: Boolean,
81
+
82
+ /**
83
+ * Whether the JS API methods should allow calling the native module methods and thus the methods
84
+ * on the controller in development. For non-expo development we want to throw
85
+ * at the JS layer since there isn't a controller set up. But for development within Expo Go
86
+ * or a Dev Client, which have their own controller/JS API implementations, we want the JS API
87
+ * calls to go through.
88
+ */
89
+ val shouldDeferToNativeForAPIMethodAvailabilityInDevelopment: Boolean
81
90
  )
82
91
  fun getConstantsForModule(): UpdatesModuleConstants
83
92
 
@@ -40,7 +40,7 @@ data class UpdatesConfiguration(
40
40
  val codeSigningMetadata: Map<String, String>?,
41
41
  val codeSigningIncludeManifestResponseCertificateChain: Boolean,
42
42
  private val codeSigningAllowUnsignedManifests: Boolean,
43
- val enableExpoUpdatesProtocolV0CompatibilityMode: Boolean, // used only in Expo Go to prevent loading rollbacks and other directives, which don't make much sense in the context of Expo Go
43
+ val enableExpoUpdatesProtocolV0CompatibilityMode: Boolean // used only in Expo Go to prevent loading rollbacks and other directives, which don't make much sense in the context of Expo Go
44
44
  ) {
45
45
  enum class CheckAutomaticallyConfiguration {
46
46
  NEVER {
@@ -55,6 +55,7 @@ data class UpdatesConfiguration(
55
55
  ALWAYS {
56
56
  override fun toJSString() = "ALWAYS"
57
57
  };
58
+
58
59
  open fun toJSString(): String {
59
60
  throw InvalidArgumentException("Unsupported CheckAutomaticallyConfiguration value")
60
61
  }
@@ -64,7 +65,7 @@ data class UpdatesConfiguration(
64
65
  expectsSignedManifest = overrideMap?.readValueCheckingType(UPDATES_CONFIGURATION_EXPECTS_EXPO_SIGNED_MANIFEST) ?: false,
65
66
  scopeKey = maybeGetDefaultScopeKey(
66
67
  overrideMap?.readValueCheckingType<String>(UPDATES_CONFIGURATION_SCOPE_KEY_KEY) ?: context?.getMetadataValue("expo.modules.updates.EXPO_SCOPE_KEY"),
67
- updateUrl = getUpdatesUrl(context, overrideMap)!!,
68
+ updateUrl = getUpdatesUrl(context, overrideMap)!!
68
69
  ),
69
70
  updateUrl = getUpdatesUrl(context, overrideMap)!!,
70
71
  sdkVersion = getSDKVersion(context, overrideMap),
@@ -102,7 +103,7 @@ data class UpdatesConfiguration(
102
103
  codeSigningAllowUnsignedManifests = overrideMap?.readValueCheckingType<Boolean>(
103
104
  UPDATES_CONFIGURATION_CODE_SIGNING_ALLOW_UNSIGNED_MANIFESTS
104
105
  ) ?: context?.getMetadataValue("expo.modules.updates.CODE_SIGNING_ALLOW_UNSIGNED_MANIFESTS") ?: false,
105
- enableExpoUpdatesProtocolV0CompatibilityMode = overrideMap?.readValueCheckingType<Boolean>(UPDATES_CONFIGURATION_ENABLE_EXPO_UPDATES_PROTOCOL_V0_COMPATIBILITY_MODE) ?: context?.getMetadataValue("expo.modules.updates.ENABLE_EXPO_UPDATES_PROTOCOL_V0_COMPATIBILITY_MODE") ?: false,
106
+ enableExpoUpdatesProtocolV0CompatibilityMode = overrideMap?.readValueCheckingType<Boolean>(UPDATES_CONFIGURATION_ENABLE_EXPO_UPDATES_PROTOCOL_V0_COMPATIBILITY_MODE) ?: context?.getMetadataValue("expo.modules.updates.ENABLE_EXPO_UPDATES_PROTOCOL_V0_COMPATIBILITY_MODE") ?: false
106
107
  )
107
108
 
108
109
  val codeSigningConfiguration: CodeSigningConfiguration? by lazy {
@@ -6,6 +6,7 @@ import com.facebook.react.ReactNativeHost
6
6
  import expo.modules.updates.loader.LoaderTask
7
7
  import expo.modules.updates.logging.UpdatesErrorCode
8
8
  import expo.modules.updates.logging.UpdatesLogger
9
+ import expo.modules.updatesinterface.UpdatesInterfaceCallbacks
9
10
 
10
11
  /**
11
12
  * Main entry point to expo-updates. Singleton that keeps track of updates state, holds references
@@ -22,6 +23,7 @@ import expo.modules.updates.logging.UpdatesLogger
22
23
  class UpdatesController {
23
24
  companion object {
24
25
  private var singletonInstance: IUpdatesController? = null
26
+
25
27
  @JvmStatic val instance: IUpdatesController
26
28
  get() {
27
29
  return checkNotNull(singletonInstance) { "UpdatesController.instance was called before the module was initialized" }
@@ -70,7 +72,7 @@ class UpdatesController {
70
72
  }
71
73
  }
72
74
 
73
- @JvmStatic fun initializeAsDevLauncherWithoutStarting(context: Context): UpdatesDevLauncherController {
75
+ @JvmStatic fun initializeAsDevLauncherWithoutStarting(context: Context, callbacks: UpdatesInterfaceCallbacks): UpdatesDevLauncherController {
74
76
  check(singletonInstance == null) { "UpdatesController must not be initialized prior to calling initializeAsDevLauncherWithoutStarting" }
75
77
 
76
78
  var updatesDirectoryException: Exception? = null
@@ -91,7 +93,8 @@ class UpdatesController {
91
93
  initialUpdatesConfiguration,
92
94
  updatesDirectory,
93
95
  updatesDirectoryException,
94
- UpdatesConfiguration.isMissingRuntimeVersion(context, null)
96
+ UpdatesConfiguration.isMissingRuntimeVersion(context, null),
97
+ callbacks
95
98
  )
96
99
  singletonInstance = instance
97
100
  return instance
@@ -23,6 +23,7 @@ import expo.modules.updates.selectionpolicy.ReaperSelectionPolicyDevelopmentClie
23
23
  import expo.modules.updates.selectionpolicy.SelectionPolicy
24
24
  import expo.modules.updates.selectionpolicy.SelectionPolicyFactory
25
25
  import expo.modules.updates.statemachine.UpdatesStateContext
26
+ import expo.modules.updatesinterface.UpdatesInterfaceCallbacks
26
27
  import expo.modules.updatesinterface.UpdatesInterface
27
28
  import org.json.JSONObject
28
29
  import java.io.File
@@ -42,7 +43,8 @@ class UpdatesDevLauncherController(
42
43
  initialUpdatesConfiguration: UpdatesConfiguration?,
43
44
  override val updatesDirectory: File?,
44
45
  private val updatesDirectoryException: Exception?,
45
- private val isMissingRuntimeVersion: Boolean
46
+ private val isMissingRuntimeVersion: Boolean,
47
+ private val callbacks: UpdatesInterfaceCallbacks
46
48
  ) : IUpdatesController, UpdatesInterface {
47
49
  override val isEmergencyLaunch = updatesDirectoryException != null
48
50
 
@@ -224,7 +226,8 @@ class UpdatesDevLauncherController(
224
226
  selectionPolicy
225
227
  )
226
228
  launcher.launch(
227
- databaseHolder.database, context,
229
+ databaseHolder.database,
230
+ context,
228
231
  object : Launcher.LauncherCallback {
229
232
  override fun onFailure(e: Exception) {
230
233
  databaseHolder.releaseDatabase()
@@ -287,13 +290,15 @@ class UpdatesDevLauncherController(
287
290
  requestHeaders = updatesConfiguration?.requestHeaders ?: mapOf(),
288
291
  localAssetFiles = localAssetFiles,
289
292
  isMissingRuntimeVersion = isMissingRuntimeVersion,
293
+ shouldDeferToNativeForAPIMethodAvailabilityInDevelopment = true
290
294
  )
291
295
  }
292
296
 
293
297
  override fun relaunchReactApplicationForModule(
294
298
  callback: IUpdatesController.ModuleCallback<Unit>
295
299
  ) {
296
- callback.onFailure(NotAvailableInDevClientException("Cannot reload update in a development client. A non-development build should be used to test this functionality."))
300
+ callbacks.onRequestRelaunch()
301
+ callback.onSuccess(Unit)
297
302
  }
298
303
 
299
304
  override fun getNativeStateMachineContext(callback: IUpdatesController.ModuleCallback<UpdatesStateContext>) {
@@ -1,3 +1,5 @@
1
+ @file:Suppress("UnusedImport") // this needs to stay for versioning to work
2
+
1
3
  package expo.modules.updates
2
4
 
3
5
  import android.content.Context
@@ -17,11 +19,6 @@ import expo.modules.updates.statemachine.UpdatesStateContext
17
19
  import java.util.Date
18
20
 
19
21
  // these unused imports must stay because of versioning
20
- /* ktlint-disable no-unused-imports */
21
- import expo.modules.updates.IUpdatesController
22
- import expo.modules.updates.UpdatesConfiguration
23
- import expo.modules.updates.UpdatesController
24
- /* ktlint-enable no-unused-imports */
25
22
 
26
23
  /**
27
24
  * Exported module which provides to the JS runtime information about the currently running update
@@ -56,7 +53,7 @@ class UpdatesModule : Module() {
56
53
  constants["runtimeVersion"] = constantsForModule.runtimeVersion ?: ""
57
54
  constants["checkAutomatically"] = constantsForModule.checkOnLaunch.toJSString()
58
55
  constants["channel"] = constantsForModule.requestHeaders["expo-channel-name"] ?: ""
59
- constants["nativeDebug"] = BuildConfig.EX_UPDATES_NATIVE_DEBUG
56
+ constants["shouldDeferToNativeForAPIMethodAvailabilityInDevelopment"] = constantsForModule.shouldDeferToNativeForAPIMethodAvailabilityInDevelopment || BuildConfig.EX_UPDATES_NATIVE_DEBUG
60
57
 
61
58
  if (launchedUpdate != null) {
62
59
  constants["updateId"] = launchedUpdate.id.toString()
@@ -222,7 +219,8 @@ class UpdatesModule : Module() {
222
219
  AsyncFunction("setExtraParamAsync") { key: String, value: String?, promise: Promise ->
223
220
  logger.debug("Called setExtraParamAsync with key = $key, value = $value")
224
221
  UpdatesController.instance.setExtraParam(
225
- key, value,
222
+ key,
223
+ value,
226
224
  object : IUpdatesController.ModuleCallback<Unit> {
227
225
  override fun onSuccess(result: Unit) {
228
226
  promise.resolve(null)
@@ -1,3 +1,5 @@
1
+ @file:Suppress("UnusedImport") // this needs to stay for versioning to work
2
+
1
3
  package expo.modules.updates
2
4
 
3
5
  import android.content.Context
@@ -18,9 +20,6 @@ import kotlinx.coroutines.launch
18
20
  import kotlinx.coroutines.withContext
19
21
 
20
22
  // these unused imports must stay because of versioning
21
- /* ktlint-disable no-unused-imports */
22
- import expo.modules.updates.UpdatesController
23
- /* ktlint-enable no-unused-imports */
24
23
 
25
24
  /**
26
25
  * Defines the internal and exported modules for expo-updates, as well as the auto-setup behavior in
@@ -155,7 +155,9 @@ object UpdatesUtils {
155
155
  return if (asset.key == null) {
156
156
  // create a filename that's unlikely to collide with any other asset
157
157
  "asset-" + Date().time + "-" + Random().nextInt() + fileExtension
158
- } else asset.key + fileExtension
158
+ } else {
159
+ asset.key + fileExtension
160
+ }
159
161
  }
160
162
 
161
163
  fun sendEventToReactNative(
@@ -64,7 +64,9 @@ class CertificateChain(private val certificateStrings: List<String>) {
64
64
  }?.let {
65
65
  if (it is DEROctetString) {
66
66
  it.octets.decodeToString()
67
- } else null
67
+ } else {
68
+ null
69
+ }
68
70
  }?.let {
69
71
  val components = it.split(',').map { component -> component.trim() }
70
72
  if (components.size != 2) {
@@ -56,7 +56,7 @@ class CodeSigningConfiguration(
56
56
  return validateSignatureInternal(
57
57
  SignatureHeaderInfo.parseSignatureHeader(signature),
58
58
  bodyBytes,
59
- manifestResponseCertificateChain,
59
+ manifestResponseCertificateChain
60
60
  )
61
61
  }
62
62
 
@@ -18,13 +18,19 @@ data class SignatureHeaderInfo(val signature: String, val keyId: String, val alg
18
18
 
19
19
  val signature = if (sigFieldValue is StringItem) {
20
20
  sigFieldValue.get()
21
- } else throw Exception("Structured field $CODE_SIGNING_SIGNATURE_STRUCTURED_FIELD_KEY_SIGNATURE not found in expo-signature header")
21
+ } else {
22
+ throw Exception("Structured field $CODE_SIGNING_SIGNATURE_STRUCTURED_FIELD_KEY_SIGNATURE not found in expo-signature header")
23
+ }
22
24
  val keyId = if (keyIdFieldValue is StringItem) {
23
25
  keyIdFieldValue.get()
24
- } else CODE_SIGNING_METADATA_DEFAULT_KEY_ID
26
+ } else {
27
+ CODE_SIGNING_METADATA_DEFAULT_KEY_ID
28
+ }
25
29
  val alg = if (algFieldValue is StringItem) {
26
30
  algFieldValue.get()
27
- } else null
31
+ } else {
32
+ null
33
+ }
28
34
 
29
35
  return SignatureHeaderInfo(signature, keyId, CodeSigningAlgorithm.parseFromString(alg))
30
36
  }
@@ -33,7 +33,7 @@ object BuildData {
33
33
 
34
34
  fun ensureBuildDataIsConsistent(
35
35
  updatesConfiguration: UpdatesConfiguration,
36
- database: UpdatesDatabase,
36
+ database: UpdatesDatabase
37
37
  ) {
38
38
  val scopeKey = updatesConfiguration.scopeKey
39
39
  val buildJSON = getBuildDataFromDatabase(database, scopeKey)
@@ -78,7 +78,7 @@ object BuildData {
78
78
 
79
79
  fun setBuildDataInDatabase(
80
80
  database: UpdatesDatabase,
81
- updatesConfiguration: UpdatesConfiguration,
81
+ updatesConfiguration: UpdatesConfiguration
82
82
  ) {
83
83
  val buildDataJSON = getBuildDataFromConfig(updatesConfiguration)
84
84
  database.jsonDataDao()?.setJSONStringForKey(
@@ -87,7 +87,9 @@ abstract class AssetDao {
87
87
  val assets = _loadAssetWithKey(key)
88
88
  return if (assets.isNotEmpty()) {
89
89
  assets[0]
90
- } else null
90
+ } else {
91
+ null
92
+ }
91
93
  }
92
94
 
93
95
  fun mergeAndUpdateAsset(existingEntity: AssetEntity, newEntity: AssetEntity) {
@@ -33,7 +33,9 @@ abstract class JSONDataDao {
33
33
  val rows = _loadJSONDataForKey(key, scopeKey)
34
34
  return if (rows.isEmpty()) {
35
35
  null
36
- } else rows[0].value
36
+ } else {
37
+ rows[0].value
38
+ }
37
39
  }
38
40
 
39
41
  @Transaction
@@ -37,7 +37,7 @@ class UpdateEntity(
37
37
  @field:ColumnInfo(name = "commit_time") var commitTime: Date,
38
38
  @field:ColumnInfo(name = "runtime_version") var runtimeVersion: String,
39
39
  @field:ColumnInfo(name = "scope_key") var scopeKey: String,
40
- @field:ColumnInfo(name = "manifest") var manifest: JSONObject,
40
+ @field:ColumnInfo(name = "manifest") var manifest: JSONObject
41
41
  ) {
42
42
  @ColumnInfo(name = "launch_asset_id")
43
43
  var launchAssetId: Long? = null
@@ -9,11 +9,13 @@ enum class UpdateStatus {
9
9
  * The update has been fully downloaded and is ready to launch.
10
10
  */
11
11
  READY,
12
+
12
13
  /**
13
14
  * The update manifest has been download from the server but not all assets have finished
14
15
  * downloading successfully.
15
16
  */
16
17
  PENDING,
18
+
17
19
  /**
18
20
  * The update has been partially loaded (copied) from its location embedded in the app bundle, but
19
21
  * not all assets have been copied successfully. The update may be able to be launched directly
@@ -21,6 +23,7 @@ enum class UpdateStatus {
21
23
  * installed.
22
24
  */
23
25
  EMBEDDED,
26
+
24
27
  /**
25
28
  * The update manifest has been downloaded and indicates that the update is being served from a
26
29
  * developer tool. It can be launched by a host application that can run a development bundle.
@@ -30,7 +30,11 @@ class EmbeddedLoader internal constructor(
30
30
  updatesDirectory: File,
31
31
  private val loaderFiles: LoaderFiles
32
32
  ) : Loader(
33
- context, configuration, database, updatesDirectory, loaderFiles
33
+ context,
34
+ configuration,
35
+ database,
36
+ updatesDirectory,
37
+ loaderFiles
34
38
  ) {
35
39
 
36
40
  constructor(
@@ -105,7 +105,7 @@ open class FileDownloader(context: Context, private val client: OkHttpClient) {
105
105
  protocolVersionRaw = responseHeaders["expo-protocol-version"],
106
106
  manifestFiltersRaw = responseHeaders["expo-manifest-filters"],
107
107
  serverDefinedHeadersRaw = responseHeaders["expo-server-defined-headers"],
108
- manifestSignature = responseHeaders["expo-manifest-signature"],
108
+ manifestSignature = responseHeaders["expo-manifest-signature"]
109
109
  )
110
110
  val responseBody = response.body
111
111
 
@@ -378,7 +378,7 @@ open class FileDownloader(context: Context, private val client: OkHttpClient) {
378
378
  val signatureValidationResult = codeSigningConfiguration.validateSignature(
379
379
  directiveResponsePartInfo.responsePartHeaderData.signature,
380
380
  body.toByteArray(),
381
- certificateChainFromManifestResponse,
381
+ certificateChainFromManifestResponse
382
382
  )
383
383
  if (signatureValidationResult.validationResult == ValidationResult.INVALID) {
384
384
  throw IOException("Directive download was successful, but signature was incorrect")
@@ -658,7 +658,7 @@ open class FileDownloader(context: Context, private val client: OkHttpClient) {
658
658
  val signatureValidationResult = codeSigningConfiguration.validateSignature(
659
659
  responsePartHeaderData.signature,
660
660
  bodyString.toByteArray(),
661
- certificateChainFromManifestResponse,
661
+ certificateChainFromManifestResponse
662
662
  )
663
663
  if (signatureValidationResult.validationResult == ValidationResult.INVALID) {
664
664
  throw IOException("Manifest download was successful, but signature was incorrect")
@@ -746,7 +746,7 @@ open class FileDownloader(context: Context, private val client: OkHttpClient) {
746
746
  internal fun createRequestForAsset(
747
747
  assetEntity: AssetEntity,
748
748
  configuration: UpdatesConfiguration,
749
- context: Context,
749
+ context: Context
750
750
  ): Request {
751
751
  return Request.Builder()
752
752
  .url(assetEntity.url!!.toString())
@@ -95,7 +95,9 @@ private fun verifyPublicRSASignature(
95
95
  val signature = Signature.getInstance("SHA256withRSA")
96
96
  val decodedPublicKey = Base64.decode(publicKeyNoComments, Base64.DEFAULT)
97
97
  val publicKeySpec = X509EncodedKeySpec(decodedPublicKey)
98
- @SuppressLint("InlinedApi") val keyFactory = KeyFactory.getInstance(KeyProperties.KEY_ALGORITHM_RSA)
98
+
99
+ @SuppressLint("InlinedApi")
100
+ val keyFactory = KeyFactory.getInstance(KeyProperties.KEY_ALGORITHM_RSA)
99
101
  val key = keyFactory.generatePublic(publicKeySpec)
100
102
  signature.initVerify(key)
101
103
  signature.update(plainText.toByteArray())
@@ -97,7 +97,9 @@ abstract class Loader protected constructor(
97
97
  this.callback = callback
98
98
 
99
99
  loadRemoteUpdate(
100
- context, database, configuration,
100
+ context,
101
+ database,
102
+ configuration,
101
103
  object : RemoteUpdateDownloadCallback {
102
104
  override fun onFailure(message: String, e: Exception) {
103
105
  finishWithError(message, e)
@@ -215,7 +217,9 @@ abstract class Loader protected constructor(
215
217
  }
216
218
 
217
219
  private enum class AssetLoadResult {
218
- FINISHED, ALREADY_EXISTS, ERRORED
220
+ FINISHED,
221
+ ALREADY_EXISTS,
222
+ ERRORED
219
223
  }
220
224
 
221
225
  private fun downloadAllAssets(assetList: List<AssetEntity>) {
@@ -234,9 +238,9 @@ abstract class Loader protected constructor(
234
238
  // if we already have a local copy of this asset, don't try to download it again!
235
239
  if (assetEntity.relativePath != null && loaderFiles.fileExists(
236
240
  File(
237
- updatesDirectory,
238
- assetEntity.relativePath
239
- )
241
+ updatesDirectory,
242
+ assetEntity.relativePath
243
+ )
240
244
  )
241
245
  ) {
242
246
  handleAssetDownloadCompleted(assetEntity, AssetLoadResult.ALREADY_EXISTS)
@@ -244,12 +248,19 @@ abstract class Loader protected constructor(
244
248
  }
245
249
 
246
250
  loadAsset(
247
- context, assetEntity, updatesDirectory, configuration,
251
+ context,
252
+ assetEntity,
253
+ updatesDirectory,
254
+ configuration,
248
255
  object : AssetDownloadCallback {
249
256
  override fun onFailure(e: Exception, assetEntity: AssetEntity) {
250
- val identifier = if (assetEntity.hash != null) "hash " + UpdatesUtils.bytesToHex(
251
- assetEntity.hash!!
252
- ) else "key " + assetEntity.key
257
+ val identifier = if (assetEntity.hash != null) {
258
+ "hash " + UpdatesUtils.bytesToHex(
259
+ assetEntity.hash!!
260
+ )
261
+ } else {
262
+ "key " + assetEntity.key
263
+ }
253
264
  Log.e(TAG, "Failed to download asset with $identifier", e)
254
265
  handleAssetDownloadCompleted(assetEntity, AssetLoadResult.ERRORED)
255
266
  }