expo-updates 57.0.14 → 57.0.15
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 +4 -0
- package/android/build.gradle +2 -2
- package/ios/EXUpdates/AppLauncher/AppLauncherWithDatabase.swift +10 -2
- package/ios/EXUpdates/AppLoader/EmbeddedAppLoader.swift +69 -7
- package/ios/EXUpdates/Database/UpdatesDatabase.swift +5 -1
- package/ios/EXUpdates/UpdatesUtils.swift +8 -0
- package/ios/EXUpdates.podspec +10 -0
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
package/android/build.gradle
CHANGED
|
@@ -42,7 +42,7 @@ expoModule {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
group = 'host.exp.exponent'
|
|
45
|
-
version = '57.0.
|
|
45
|
+
version = '57.0.15'
|
|
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 '57.0.
|
|
92
|
+
versionName '57.0.15'
|
|
93
93
|
consumerProguardFiles("proguard-rules.pro")
|
|
94
94
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
|
95
95
|
|
|
@@ -32,6 +32,11 @@ public class AppLauncherWithDatabase: NSObject, AppLauncher {
|
|
|
32
32
|
public var launchAssetUrl: URL?
|
|
33
33
|
public var assetFilesMap: [String: String]?
|
|
34
34
|
|
|
35
|
+
/// Set when the launched update is served directly from the embedded app binary. Tracked
|
|
36
|
+
/// explicitly because `assetFilesMap` is now populated with the bundle-resolved embedded assets,
|
|
37
|
+
/// so it can no longer double as the "using embedded assets" signal.
|
|
38
|
+
private var launchedFromEmbeddedBundle = false
|
|
39
|
+
|
|
35
40
|
private let launcherQueue: DispatchQueue
|
|
36
41
|
private var completedAssets: Int
|
|
37
42
|
private let config: UpdatesConfig
|
|
@@ -54,7 +59,7 @@ public class AppLauncherWithDatabase: NSObject, AppLauncher {
|
|
|
54
59
|
}
|
|
55
60
|
|
|
56
61
|
public func isUsingEmbeddedAssets() -> Bool {
|
|
57
|
-
return
|
|
62
|
+
return launchedFromEmbeddedBundle
|
|
58
63
|
}
|
|
59
64
|
|
|
60
65
|
public static func launchableUpdate(
|
|
@@ -178,7 +183,10 @@ public class AppLauncherWithDatabase: NSObject, AppLauncher {
|
|
|
178
183
|
}
|
|
179
184
|
|
|
180
185
|
if launchedUpdate.status == UpdateStatus.StatusEmbedded {
|
|
181
|
-
|
|
186
|
+
launchedFromEmbeddedBundle = true
|
|
187
|
+
// The embedded update's assets aren't copied into the cache, so resolve them from the app
|
|
188
|
+
// binary. Populating the map here keeps `Updates.localAssets` available instead of empty.
|
|
189
|
+
assetFilesMap = UpdatesUtils.embeddedAssetsMap(withConfig: config, database: database, logger: logger)
|
|
182
190
|
launchAssetUrl = updatesBundle.url(
|
|
183
191
|
forResource: EmbeddedAppLoader.EXUpdatesBareEmbeddedBundleFilename,
|
|
184
192
|
withExtension: EmbeddedAppLoader.EXUpdatesBareEmbeddedBundleFileType
|
|
@@ -8,14 +8,12 @@
|
|
|
8
8
|
import Foundation
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* Subclass of AppLoader which
|
|
12
|
-
* expo-updates cache location.
|
|
11
|
+
* Subclass of AppLoader which loads the embedded update.
|
|
13
12
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* redownloaded if included in future updates.
|
|
13
|
+
* By default (`EX_UPDATES_COPY_EMBEDDED_ASSETS` off) the update is registered but its assets aren't
|
|
14
|
+
* read into the database; it keeps StatusEmbedded and launches from the app binary, so first launch
|
|
15
|
+
* stays fast. When the flag is on, assets are read into the database and it launches like any other
|
|
16
|
+
* update, so a later update reusing them avoids a redownload.
|
|
19
17
|
*/
|
|
20
18
|
@objc(EXUpdatesEmbeddedAppLoader)
|
|
21
19
|
@objcMembers
|
|
@@ -29,6 +27,24 @@ public final class EmbeddedAppLoader: AppLoader {
|
|
|
29
27
|
|
|
30
28
|
private static var embeddedManifestInternal: EmbeddedUpdate?
|
|
31
29
|
|
|
30
|
+
/// Whether to read and hash embedded assets into the database on first launch. Defaults to the
|
|
31
|
+
/// build-time `EX_UPDATES_COPY_EMBEDDED_ASSETS` flag (off). Overridable for testing.
|
|
32
|
+
internal var shouldCopyEmbeddedAssets: Bool = UpdatesUtils.shouldCopyEmbeddedAssets()
|
|
33
|
+
|
|
34
|
+
internal let completionQueue: DispatchQueue
|
|
35
|
+
|
|
36
|
+
public required override init(
|
|
37
|
+
config: UpdatesConfig,
|
|
38
|
+
logger: UpdatesLogger,
|
|
39
|
+
database: UpdatesDatabase,
|
|
40
|
+
directory: URL,
|
|
41
|
+
launchedUpdate: Update?,
|
|
42
|
+
completionQueue: DispatchQueue
|
|
43
|
+
) {
|
|
44
|
+
self.completionQueue = completionQueue
|
|
45
|
+
super.init(config: config, logger: logger, database: database, directory: directory, launchedUpdate: launchedUpdate, completionQueue: completionQueue)
|
|
46
|
+
}
|
|
47
|
+
|
|
32
48
|
/**
|
|
33
49
|
Gets the embedded update.
|
|
34
50
|
If the `UpdatesConfig.hasEmbeddedUpdate` is false, it returns nil
|
|
@@ -136,6 +152,18 @@ public final class EmbeddedAppLoader: AppLoader {
|
|
|
136
152
|
self.assetBlock = assetBlock
|
|
137
153
|
self.successBlock = successBlock
|
|
138
154
|
self.errorBlock = errorBlock
|
|
155
|
+
startEmbeddedLoad(fromEmbeddedManifest: embeddedManifest)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/// Loads the embedded update: with copying off (default) registers it without ingesting assets,
|
|
159
|
+
/// otherwise loads them like any other update. Separate from `loadUpdateResponseFromEmbeddedManifest`
|
|
160
|
+
/// so tests can pass a manifest without reading the bundle.
|
|
161
|
+
internal func startEmbeddedLoad(fromEmbeddedManifest embeddedManifest: Update) {
|
|
162
|
+
if !shouldCopyEmbeddedAssets {
|
|
163
|
+
registerEmbeddedUpdateWithoutCopying(embeddedManifest)
|
|
164
|
+
return
|
|
165
|
+
}
|
|
166
|
+
|
|
139
167
|
startLoading(fromUpdateResponse: UpdateResponse(
|
|
140
168
|
responseHeaderData: nil,
|
|
141
169
|
manifestUpdateResponsePart: ManifestUpdateResponsePart(updateManifest: embeddedManifest),
|
|
@@ -143,6 +171,40 @@ public final class EmbeddedAppLoader: AppLoader {
|
|
|
143
171
|
))
|
|
144
172
|
}
|
|
145
173
|
|
|
174
|
+
/// Registers the embedded update without reading, hashing, or copying its assets. A StatusEmbedded
|
|
175
|
+
/// update resolves its bundle and assets from the app binary at launch. Tradeoff: a future update
|
|
176
|
+
/// reusing an embedded asset re-downloads it.
|
|
177
|
+
private func registerEmbeddedUpdateWithoutCopying(_ embeddedManifest: Update) {
|
|
178
|
+
database.databaseQueue.async {
|
|
179
|
+
do {
|
|
180
|
+
let existingUpdate = try? self.database.update(withId: embeddedManifest.updateId, config: self.config)
|
|
181
|
+
if existingUpdate == nil {
|
|
182
|
+
try self.database.addUpdate(embeddedManifest, config: self.config)
|
|
183
|
+
}
|
|
184
|
+
// Mark finished (keep = 1) so the reaper retains it; it stays StatusEmbedded since copying is off.
|
|
185
|
+
try self.database.markUpdateFinished(embeddedManifest)
|
|
186
|
+
} catch {
|
|
187
|
+
let errorBlock = self.errorBlock
|
|
188
|
+
self.completionQueue.async {
|
|
189
|
+
errorBlock?(UpdatesError.appLoaderUnknownError(cause: error))
|
|
190
|
+
self.reset()
|
|
191
|
+
}
|
|
192
|
+
return
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
let successBlock = self.successBlock
|
|
196
|
+
let updateResponse = UpdateResponse(
|
|
197
|
+
responseHeaderData: nil,
|
|
198
|
+
manifestUpdateResponsePart: ManifestUpdateResponsePart(updateManifest: embeddedManifest),
|
|
199
|
+
directiveUpdateResponsePart: nil
|
|
200
|
+
)
|
|
201
|
+
self.completionQueue.async {
|
|
202
|
+
successBlock?(updateResponse)
|
|
203
|
+
self.reset()
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
146
208
|
override public func downloadAsset(_ asset: UpdateAsset, extraHeaders: [String: Any]) {
|
|
147
209
|
FileDownloader.assetFilesQueue.async {
|
|
148
210
|
self.handleAssetDownloadAlreadyExists(asset)
|
|
@@ -280,7 +280,11 @@ public final class UpdatesDatabase: NSObject {
|
|
|
280
280
|
}
|
|
281
281
|
|
|
282
282
|
public func markUpdateFinished(_ update: Update) throws {
|
|
283
|
-
|
|
283
|
+
// With copying off, embedded updates have no asset rows, so they must stay StatusEmbedded to keep
|
|
284
|
+
// launching from the bundle. Promoting to StatusReady would route launch through the database
|
|
285
|
+
// asset path, which has no rows for them.
|
|
286
|
+
let keepEmbedded = update.status == UpdateStatus.StatusEmbedded && !UpdatesUtils.shouldCopyEmbeddedAssets()
|
|
287
|
+
if update.status != UpdateStatus.StatusDevelopment && !keepEmbedded {
|
|
284
288
|
update.status = UpdateStatus.StatusReady
|
|
285
289
|
}
|
|
286
290
|
|
|
@@ -182,6 +182,14 @@ public final class UpdatesUtils: NSObject {
|
|
|
182
182
|
#endif
|
|
183
183
|
}
|
|
184
184
|
|
|
185
|
+
internal static func shouldCopyEmbeddedAssets() -> Bool {
|
|
186
|
+
#if EX_UPDATES_COPY_EMBEDDED_ASSETS
|
|
187
|
+
return true
|
|
188
|
+
#else
|
|
189
|
+
return false
|
|
190
|
+
#endif
|
|
191
|
+
}
|
|
192
|
+
|
|
185
193
|
internal static func runBlockOnMainThread(_ block: @escaping () -> Void) {
|
|
186
194
|
if Thread.isMainThread {
|
|
187
195
|
block()
|
package/ios/EXUpdates.podspec
CHANGED
|
@@ -9,6 +9,9 @@ end
|
|
|
9
9
|
if ENV['EX_UPDATES_CUSTOM_INIT'] != '1'
|
|
10
10
|
ENV['EX_UPDATES_CUSTOM_INIT'] = podfile_properties['updatesCustomInit'] == 'true' ? '1' : '0'
|
|
11
11
|
end
|
|
12
|
+
if ENV['EX_UPDATES_COPY_EMBEDDED_ASSETS'] != '1'
|
|
13
|
+
ENV['EX_UPDATES_COPY_EMBEDDED_ASSETS'] = podfile_properties['updatesCopyEmbeddedAssets'] == 'true' ? '1' : '0'
|
|
14
|
+
end
|
|
12
15
|
|
|
13
16
|
use_dev_client = false
|
|
14
17
|
begin
|
|
@@ -72,6 +75,7 @@ Pod::Spec.new do |s|
|
|
|
72
75
|
|
|
73
76
|
ex_updates_native_debug = ENV['EX_UPDATES_NATIVE_DEBUG'] == '1'
|
|
74
77
|
ex_updates_custom_init = ENV['EX_UPDATES_CUSTOM_INIT'] == '1'
|
|
78
|
+
ex_updates_copy_embedded_assets = ENV['EX_UPDATES_COPY_EMBEDDED_ASSETS'] == '1'
|
|
75
79
|
if ex_updates_native_debug
|
|
76
80
|
other_debug_c_flags << ' -DEX_UPDATES_NATIVE_DEBUG=1'
|
|
77
81
|
other_debug_swift_flags << ' -DEX_UPDATES_NATIVE_DEBUG'
|
|
@@ -82,6 +86,12 @@ Pod::Spec.new do |s|
|
|
|
82
86
|
other_release_c_flags << ' -DEX_UPDATES_CUSTOM_INIT=1'
|
|
83
87
|
other_release_swift_flags << ' -DEX_UPDATES_CUSTOM_INIT'
|
|
84
88
|
end
|
|
89
|
+
if ex_updates_copy_embedded_assets
|
|
90
|
+
other_debug_c_flags << ' -DEX_UPDATES_COPY_EMBEDDED_ASSETS=1'
|
|
91
|
+
other_debug_swift_flags << ' -DEX_UPDATES_COPY_EMBEDDED_ASSETS'
|
|
92
|
+
other_release_c_flags << ' -DEX_UPDATES_COPY_EMBEDDED_ASSETS=1'
|
|
93
|
+
other_release_swift_flags << ' -DEX_UPDATES_COPY_EMBEDDED_ASSETS'
|
|
94
|
+
end
|
|
85
95
|
if use_dev_client
|
|
86
96
|
other_debug_c_flags << ' -DUSE_DEV_CLIENT=1'
|
|
87
97
|
other_debug_swift_flags << ' -DUSE_DEV_CLIENT'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-updates",
|
|
3
|
-
"version": "57.0.
|
|
3
|
+
"version": "57.0.15",
|
|
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",
|
|
@@ -60,9 +60,9 @@
|
|
|
60
60
|
"picomatch": "^4.0.4",
|
|
61
61
|
"ts-node": "^10.9.2",
|
|
62
62
|
"xstate": "^4.37.2",
|
|
63
|
+
"expo": "57.0.14",
|
|
63
64
|
"@expo/metro-config": "57.0.8",
|
|
64
|
-
"expo-dev-client": "57.0.
|
|
65
|
-
"expo": "57.0.13",
|
|
65
|
+
"expo-dev-client": "57.0.13",
|
|
66
66
|
"expo-module-scripts": "56.0.3"
|
|
67
67
|
},
|
|
68
68
|
"peerDependencies": {
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
"./scripts/with-node.sh"
|
|
83
83
|
]
|
|
84
84
|
},
|
|
85
|
-
"gitHead": "
|
|
85
|
+
"gitHead": "391d762fa5059cebf63ef2381da93994ce97fc63",
|
|
86
86
|
"scripts": {
|
|
87
87
|
"build": "expo-module build",
|
|
88
88
|
"clean": "expo-module clean",
|