expo-updates 55.0.27 → 55.0.28
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.
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,16 @@
|
|
|
10
10
|
|
|
11
11
|
### 💡 Others
|
|
12
12
|
|
|
13
|
+
## 55.0.28 — 2026-08-25
|
|
14
|
+
|
|
15
|
+
### 🐛 Bug fixes
|
|
16
|
+
|
|
17
|
+
- [Android] Register the embedded update in a single transaction. An interrupted registration previously left an update row with no launch asset, which is treated as launchable and then fails every cold start with "Launch asset not found for update"; it now leaves no row, so the next launch registers it cleanly. ([#49130](https://github.com/expo/expo/pull/49130) by [@gwdp](https://github.com/gwdp))
|
|
18
|
+
|
|
19
|
+
### 💡 Others
|
|
20
|
+
|
|
21
|
+
- [Android] Replace the "this should never happen" wording in the missing launch asset error with the likely cause and how the state resolves. ([#49130](https://github.com/expo/expo/pull/49130) by [@gwdp](https://github.com/gwdp))
|
|
22
|
+
|
|
13
23
|
## 55.0.27 — 2026-08-17
|
|
14
24
|
|
|
15
25
|
### 🐛 Bug fixes
|
package/android/build.gradle
CHANGED
|
@@ -42,7 +42,7 @@ expoModule {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
group = 'host.exp.exponent'
|
|
45
|
-
version = '55.0.
|
|
45
|
+
version = '55.0.28'
|
|
46
46
|
|
|
47
47
|
// Utility method to derive boolean values from the environment or from Java properties,
|
|
48
48
|
// and return them as strings to be used in BuildConfig fields
|
|
@@ -89,7 +89,7 @@ android {
|
|
|
89
89
|
namespace "expo.modules.updates"
|
|
90
90
|
defaultConfig {
|
|
91
91
|
versionCode 31
|
|
92
|
-
versionName '55.0.
|
|
92
|
+
versionName '55.0.28'
|
|
93
93
|
consumerProguardFiles("proguard-rules.pro")
|
|
94
94
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
|
95
95
|
|
|
@@ -87,7 +87,7 @@ class DatabaseLauncher(
|
|
|
87
87
|
// verify that we have all assets on disk
|
|
88
88
|
// according to the database, we should, but something could have gone wrong on disk
|
|
89
89
|
val launchAsset = database.updateDao().loadLaunchAssetForUpdate(launchedUpdate!!.id)
|
|
90
|
-
?: throw Exception("Launch asset not found for update; this
|
|
90
|
+
?: throw Exception("Launch asset not found for update. The update row has no launch asset; an interrupted registration in an older version of expo-updates can leave an update in this state, and it is replaced once a newer update is downloaded. Debug info: ${launchedUpdate!!.debugInfo()}")
|
|
91
91
|
|
|
92
92
|
if (launchAsset.relativePath == null) {
|
|
93
93
|
throw Exception("Launch asset relative path should not be null. Debug info: ${launchedUpdate!!.debugInfo()}")
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
package expo.modules.updates.loader
|
|
2
2
|
|
|
3
3
|
import android.content.Context
|
|
4
|
+
import androidx.room.withTransaction
|
|
4
5
|
import expo.modules.updates.UpdatesConfiguration
|
|
5
6
|
import expo.modules.updates.UpdatesUtils
|
|
6
7
|
import expo.modules.updates.db.UpdatesDatabase
|
|
@@ -17,6 +18,7 @@ import expo.modules.updates.logging.UpdatesErrorCode
|
|
|
17
18
|
import expo.modules.updates.logging.UpdatesLogger
|
|
18
19
|
import expo.modules.updates.manifest.ManifestMetadata
|
|
19
20
|
import expo.modules.updates.manifest.Update
|
|
21
|
+
import kotlinx.coroutines.CancellationException
|
|
20
22
|
import kotlinx.coroutines.CoroutineScope
|
|
21
23
|
import kotlinx.coroutines.Dispatchers
|
|
22
24
|
import kotlinx.coroutines.SupervisorJob
|
|
@@ -168,16 +170,23 @@ abstract class Loader protected constructor(
|
|
|
168
170
|
updateEntity = existingUpdateEntity
|
|
169
171
|
return finish()
|
|
170
172
|
} else {
|
|
173
|
+
val insertUpdateEntityOnFinish: Boolean
|
|
171
174
|
if (existingUpdateEntity == null) {
|
|
172
|
-
// no update already exists with this ID, so we need to
|
|
175
|
+
// no update already exists with this ID, so we need to download everything.
|
|
173
176
|
updateEntity = newUpdateEntity
|
|
174
|
-
|
|
177
|
+
// EMBEDDED is already in the launchable set, so a row inserted before its launch asset exists
|
|
178
|
+
// gets picked as launchable and then fails every launch.
|
|
179
|
+
insertUpdateEntityOnFinish = newUpdateEntity.status == UpdateStatus.EMBEDDED
|
|
180
|
+
if (!insertUpdateEntityOnFinish) {
|
|
181
|
+
database.updateDao().insertUpdate(updateEntity!!)
|
|
182
|
+
}
|
|
175
183
|
} else {
|
|
176
184
|
// we've already partially downloaded the update, so we should use the existing entity.
|
|
177
185
|
// however, it's not ready, so we should try to download all the assets again.
|
|
178
186
|
updateEntity = existingUpdateEntity
|
|
187
|
+
insertUpdateEntityOnFinish = false
|
|
179
188
|
}
|
|
180
|
-
return downloadAllAssets(update)
|
|
189
|
+
return downloadAllAssets(update, insertUpdateEntityOnFinish)
|
|
181
190
|
}
|
|
182
191
|
}
|
|
183
192
|
|
|
@@ -187,7 +196,7 @@ abstract class Loader protected constructor(
|
|
|
187
196
|
ERRORED
|
|
188
197
|
}
|
|
189
198
|
|
|
190
|
-
private suspend fun downloadAllAssets(update: Update): LoaderResult {
|
|
199
|
+
private suspend fun downloadAllAssets(update: Update, insertUpdateEntityOnFinish: Boolean): LoaderResult {
|
|
191
200
|
val assetList = update.assetEntityList.distinctBy { it.key }
|
|
192
201
|
assetTotal = assetList.size
|
|
193
202
|
|
|
@@ -234,26 +243,34 @@ abstract class Loader protected constructor(
|
|
|
234
243
|
assetDownloadJobs.awaitAll()
|
|
235
244
|
|
|
236
245
|
try {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
.
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
246
|
+
database.withTransaction {
|
|
247
|
+
if (insertUpdateEntityOnFinish) {
|
|
248
|
+
database.updateDao().insertUpdate(updateEntity!!)
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
for (asset in existingAssetList) {
|
|
252
|
+
val existingAssetFound = database.assetDao()
|
|
253
|
+
.addExistingAssetToUpdate(updateEntity!!, asset, asset.isLaunchAsset)
|
|
254
|
+
if (!existingAssetFound) {
|
|
255
|
+
// the database and filesystem have gotten out of sync
|
|
256
|
+
// do our best to create a new entry for this file even though it already existed on disk
|
|
257
|
+
// TODO: we should probably get rid of this assumption that if an asset exists on disk with the same filename, it's the same asset
|
|
258
|
+
var hash: ByteArray? = null
|
|
259
|
+
try {
|
|
260
|
+
hash = UpdatesUtils.sha256(File(updatesDirectory, asset.relativePath))
|
|
261
|
+
} catch (_: Exception) {
|
|
262
|
+
}
|
|
263
|
+
asset.downloadTime = Date()
|
|
264
|
+
asset.hash = hash
|
|
265
|
+
finishedAssetList.add(asset)
|
|
248
266
|
}
|
|
249
|
-
asset.downloadTime = Date()
|
|
250
|
-
asset.hash = hash
|
|
251
|
-
finishedAssetList.add(asset)
|
|
252
267
|
}
|
|
253
|
-
}
|
|
254
268
|
|
|
255
|
-
|
|
256
|
-
|
|
269
|
+
database.assetDao().insertAssets(finishedAssetList, updateEntity!!)
|
|
270
|
+
database.updateDao().markUpdateFinished(updateEntity!!)
|
|
271
|
+
}
|
|
272
|
+
} catch (e: CancellationException) {
|
|
273
|
+
throw e
|
|
257
274
|
} catch (e: Exception) {
|
|
258
275
|
throw IOException("Error while adding new update to database", e)
|
|
259
276
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-updates",
|
|
3
|
-
"version": "55.0.
|
|
3
|
+
"version": "55.0.28",
|
|
4
4
|
"description": "Fetches and manages remotely-hosted assets and updates to your app's JS bundle.",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"chalk": "^4.1.2",
|
|
46
46
|
"debug": "^4.3.4",
|
|
47
47
|
"expo-eas-client": "~55.0.5",
|
|
48
|
-
"expo-manifests": "~55.0.
|
|
48
|
+
"expo-manifests": "~55.0.21",
|
|
49
49
|
"expo-structured-headers": "~55.0.2",
|
|
50
50
|
"expo-updates-interface": "~55.1.6",
|
|
51
51
|
"getenv": "^2.0.0",
|
|
@@ -71,5 +71,5 @@
|
|
|
71
71
|
"react": "*",
|
|
72
72
|
"react-native": "*"
|
|
73
73
|
},
|
|
74
|
-
"gitHead": "
|
|
74
|
+
"gitHead": "856b99321eeb04bd528b33f90c0e7fa2859a1fcb"
|
|
75
75
|
}
|