@hot-updater/react-native 1.0.6 → 1.0.7
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/android/src/newarch/HotUpdaterModule.kt +108 -57
- package/android/src/oldarch/HotUpdaterModule.kt +109 -57
- package/android/src/oldarch/HotUpdaterSpec.kt +5 -0
- package/ios/HotUpdater/Interface/HotUpdaterInterface.h +3 -0
- package/ios/HotUpdater/Internal/HotUpdater.mm +49 -0
- package/ios/HotUpdater/Internal/HotUpdaterImpl.swift +150 -62
- package/lib/commonjs/checkForUpdate.js +16 -9
- package/lib/commonjs/checkForUpdate.js.map +1 -1
- package/lib/commonjs/httpClient.js +14 -20
- package/lib/commonjs/httpClient.js.map +1 -1
- package/lib/commonjs/native.js +36 -10
- package/lib/commonjs/native.js.map +1 -1
- package/lib/commonjs/sdkVersion.js +1 -1
- package/lib/commonjs/specs/NativeHotUpdater.js +5 -0
- package/lib/commonjs/specs/NativeHotUpdater.js.map +1 -1
- package/lib/module/checkForUpdate.js +17 -10
- package/lib/module/checkForUpdate.js.map +1 -1
- package/lib/module/httpClient.js +14 -20
- package/lib/module/httpClient.js.map +1 -1
- package/lib/module/native.js +35 -10
- package/lib/module/native.js.map +1 -1
- package/lib/module/sdkVersion.js +1 -1
- package/lib/module/specs/NativeHotUpdater.js +7 -0
- package/lib/module/specs/NativeHotUpdater.js.map +1 -1
- package/lib/typescript/commonjs/checkForUpdate.d.ts.map +1 -1
- package/lib/typescript/commonjs/httpClient.d.ts +20 -12
- package/lib/typescript/commonjs/httpClient.d.ts.map +1 -1
- package/lib/typescript/commonjs/native.d.ts +17 -3
- package/lib/typescript/commonjs/native.d.ts.map +1 -1
- package/lib/typescript/commonjs/sdkVersion.d.ts +1 -1
- package/lib/typescript/commonjs/specs/NativeHotUpdater.d.ts +31 -7
- package/lib/typescript/commonjs/specs/NativeHotUpdater.d.ts.map +1 -1
- package/lib/typescript/module/checkForUpdate.d.ts.map +1 -1
- package/lib/typescript/module/httpClient.d.ts +20 -12
- package/lib/typescript/module/httpClient.d.ts.map +1 -1
- package/lib/typescript/module/native.d.ts +17 -3
- package/lib/typescript/module/native.d.ts.map +1 -1
- package/lib/typescript/module/sdkVersion.d.ts +1 -1
- package/lib/typescript/module/specs/NativeHotUpdater.d.ts +31 -7
- package/lib/typescript/module/specs/NativeHotUpdater.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/checkForUpdate.ts +13 -8
- package/src/httpClient.ts +35 -31
- package/src/native.ts +53 -16
- package/src/sdkVersion.ts +1 -1
- package/src/specs/NativeHotUpdater.ts +33 -7
|
@@ -47,7 +47,14 @@ class HotUpdaterModule internal constructor(
|
|
|
47
47
|
*/
|
|
48
48
|
private fun getInstance(): HotUpdaterImpl = HotUpdater.getInstance(mReactApplicationContext)
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
/**
|
|
51
|
+
* Every changed file with its hash and URL or Hermes patch; with
|
|
52
|
+
* [requireFileHash] false, also entries that hold only the Hermes patch.
|
|
53
|
+
*/
|
|
54
|
+
private fun parseAssets(
|
|
55
|
+
params: ReadableMap,
|
|
56
|
+
requireFileHash: Boolean,
|
|
57
|
+
): Map<String, ChangedAssetDescriptor>? {
|
|
51
58
|
if (!params.hasKey("assets") || params.isNull("assets")) {
|
|
52
59
|
return null
|
|
53
60
|
}
|
|
@@ -59,39 +66,10 @@ class HotUpdaterModule internal constructor(
|
|
|
59
66
|
while (iterator.hasNextKey()) {
|
|
60
67
|
val assetPath = iterator.nextKey()
|
|
61
68
|
val assetMap = changedAssetsMap.getMap(assetPath) ?: continue
|
|
62
|
-
// In artifact protocol v2, an entry holds only the Hermes patch.
|
|
63
69
|
val assetHash = if (assetMap.hasKey("fileHash")) assetMap.getString("fileHash") else null
|
|
70
|
+
if (assetHash == null && requireFileHash) continue
|
|
64
71
|
val patchMap = assetMap.getMap("patch")
|
|
65
|
-
val patch =
|
|
66
|
-
if (patchMap != null) {
|
|
67
|
-
val algorithm = patchMap.getString("algorithm")
|
|
68
|
-
val baseBundleId = patchMap.getString("baseBundleId")
|
|
69
|
-
val baseFileHash = patchMap.getString("baseFileHash")
|
|
70
|
-
val patchFileHash = patchMap.getString("patchFileHash")
|
|
71
|
-
val patchUrl = patchMap.getString("patchUrl")
|
|
72
|
-
val byteSize = readSafeInteger(patchMap, "byteSize")
|
|
73
|
-
|
|
74
|
-
if (
|
|
75
|
-
algorithm != null &&
|
|
76
|
-
baseBundleId != null &&
|
|
77
|
-
baseFileHash != null &&
|
|
78
|
-
patchFileHash != null &&
|
|
79
|
-
patchUrl != null
|
|
80
|
-
) {
|
|
81
|
-
BsdiffPatchDescriptor(
|
|
82
|
-
algorithm = algorithm,
|
|
83
|
-
baseBundleId = baseBundleId,
|
|
84
|
-
baseFileHash = baseFileHash,
|
|
85
|
-
patchFileHash = patchFileHash,
|
|
86
|
-
patchUrl = patchUrl,
|
|
87
|
-
byteSize = byteSize,
|
|
88
|
-
)
|
|
89
|
-
} else {
|
|
90
|
-
null
|
|
91
|
-
}
|
|
92
|
-
} else {
|
|
93
|
-
null
|
|
94
|
-
}
|
|
72
|
+
val patch = parsePatch(patchMap)
|
|
95
73
|
val fileMap =
|
|
96
74
|
if (assetMap.hasKey("file") && !assetMap.isNull("file")) {
|
|
97
75
|
assetMap.getMap("file")
|
|
@@ -138,6 +116,79 @@ class HotUpdaterModule internal constructor(
|
|
|
138
116
|
return parsed
|
|
139
117
|
}
|
|
140
118
|
|
|
119
|
+
private fun parsePatch(patchMap: ReadableMap?): BsdiffPatchDescriptor? {
|
|
120
|
+
if (patchMap == null) return null
|
|
121
|
+
val algorithm = patchMap.getString("algorithm")
|
|
122
|
+
val baseBundleId = patchMap.getString("baseBundleId")
|
|
123
|
+
val baseFileHash = patchMap.getString("baseFileHash")
|
|
124
|
+
val patchFileHash = patchMap.getString("patchFileHash")
|
|
125
|
+
val patchUrl = patchMap.getString("patchUrl")
|
|
126
|
+
val byteSize = readSafeInteger(patchMap, "byteSize")
|
|
127
|
+
|
|
128
|
+
return if (
|
|
129
|
+
algorithm != null &&
|
|
130
|
+
baseBundleId != null &&
|
|
131
|
+
baseFileHash != null &&
|
|
132
|
+
patchFileHash != null &&
|
|
133
|
+
patchUrl != null
|
|
134
|
+
) {
|
|
135
|
+
BsdiffPatchDescriptor(
|
|
136
|
+
algorithm = algorithm,
|
|
137
|
+
baseBundleId = baseBundleId,
|
|
138
|
+
baseFileHash = baseFileHash,
|
|
139
|
+
patchFileHash = patchFileHash,
|
|
140
|
+
patchUrl = patchUrl,
|
|
141
|
+
byteSize = byteSize,
|
|
142
|
+
)
|
|
143
|
+
} else {
|
|
144
|
+
null
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* The resolver that asks `filesUrl` for the files native downloads one by
|
|
150
|
+
* one; null when `filesUrl` is missing.
|
|
151
|
+
*/
|
|
152
|
+
private fun parseFileResolver(params: ReadableMap): ArtifactFileResolver? {
|
|
153
|
+
val filesUrl =
|
|
154
|
+
if (params.hasKey("filesUrl") && !params.isNull("filesUrl")) {
|
|
155
|
+
params.getString("filesUrl")?.takeIf { it.isNotEmpty() }
|
|
156
|
+
} else {
|
|
157
|
+
null
|
|
158
|
+
} ?: return null
|
|
159
|
+
try {
|
|
160
|
+
java.net.URL(filesUrl)
|
|
161
|
+
} catch (e: java.net.MalformedURLException) {
|
|
162
|
+
throw HotUpdaterException.invalidFileUrl("filesUrl", filesUrl, UpdateFailureResource.FILE)
|
|
163
|
+
}
|
|
164
|
+
val requestTimeoutMs =
|
|
165
|
+
if (params.hasKey("requestTimeout") && !params.isNull("requestTimeout")) {
|
|
166
|
+
params.getDouble("requestTimeout").toLong().takeIf { it > 0 }
|
|
167
|
+
} else {
|
|
168
|
+
null
|
|
169
|
+
} ?: HttpArtifactFileResolver.DEFAULT_TIMEOUT_MS
|
|
170
|
+
return HttpArtifactFileResolver(filesUrl, parseRequestHeaders(params), requestTimeoutMs)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Artifact protocol v2: the Hermes patch as the only planned asset, and
|
|
175
|
+
* the resolver that asks `filesUrl` for the files native downloads one by
|
|
176
|
+
* one; null when `filesUrl` is missing.
|
|
177
|
+
*/
|
|
178
|
+
private fun parseArtifactInstall(params: ReadableMap): Pair<Map<String, ChangedAssetDescriptor>, ArtifactFileResolver?>? {
|
|
179
|
+
val fileResolver = parseFileResolver(params) ?: return null
|
|
180
|
+
val patchMap = if (params.hasKey("patch") && !params.isNull("patch")) params.getMap("patch") else null
|
|
181
|
+
val assetPath = patchMap?.getString("assetPath")
|
|
182
|
+
val patch = parsePatch(patchMap)
|
|
183
|
+
val assets =
|
|
184
|
+
if (assetPath != null && patch != null) {
|
|
185
|
+
mapOf(assetPath to ChangedAssetDescriptor(fileUrl = null, fileHash = "", patch = patch))
|
|
186
|
+
} else {
|
|
187
|
+
emptyMap()
|
|
188
|
+
}
|
|
189
|
+
return assets to fileResolver
|
|
190
|
+
}
|
|
191
|
+
|
|
141
192
|
private fun parseSelection(params: ReadableMap): PersistedSelection? {
|
|
142
193
|
if (!params.hasKey("selection") || params.isNull("selection")) return null
|
|
143
194
|
val selection = params.getMap("selection") ?: return null
|
|
@@ -188,6 +239,28 @@ class HotUpdaterModule internal constructor(
|
|
|
188
239
|
override fun updateBundle(
|
|
189
240
|
params: ReadableMap,
|
|
190
241
|
promise: Promise,
|
|
242
|
+
) {
|
|
243
|
+
// Legacy: artifact protocol v1, where every file comes with its URL.
|
|
244
|
+
// JavaScript from the first protocol v2 SDK also sends `filesUrl`
|
|
245
|
+
// here, with only the Hermes patch in `assets`; its OTA Bundles must
|
|
246
|
+
// still install.
|
|
247
|
+
stage(params, promise) {
|
|
248
|
+
val fileResolver = parseFileResolver(params)
|
|
249
|
+
parseAssets(params, requireFileHash = fileResolver == null)?.let { it to fileResolver }
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
override fun installArtifact(
|
|
254
|
+
params: ReadableMap,
|
|
255
|
+
promise: Promise,
|
|
256
|
+
) {
|
|
257
|
+
stage(params, promise) { parseArtifactInstall(params) }
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
private fun stage(
|
|
261
|
+
params: ReadableMap,
|
|
262
|
+
promise: Promise,
|
|
263
|
+
plan: () -> Pair<Map<String, ChangedAssetDescriptor>, ArtifactFileResolver?>?,
|
|
191
264
|
) {
|
|
192
265
|
moduleScope.launch {
|
|
193
266
|
try {
|
|
@@ -199,7 +272,8 @@ class HotUpdaterModule internal constructor(
|
|
|
199
272
|
|
|
200
273
|
val manifestUrl = params.getString("manifestUrl")
|
|
201
274
|
val manifestFileHash = params.getString("manifestFileHash")
|
|
202
|
-
val
|
|
275
|
+
val planned = plan()
|
|
276
|
+
val assets = planned?.first
|
|
203
277
|
if (manifestUrl.isNullOrEmpty() || manifestFileHash.isNullOrEmpty() || assets == null) {
|
|
204
278
|
promise.rejectUpdateBundle(HotUpdaterException.invalidManifestParams())
|
|
205
279
|
return@launch
|
|
@@ -230,30 +304,7 @@ class HotUpdaterModule internal constructor(
|
|
|
230
304
|
}
|
|
231
305
|
}
|
|
232
306
|
val selection = parseSelection(params)
|
|
233
|
-
val
|
|
234
|
-
if (params.hasKey("filesUrl") && !params.isNull("filesUrl")) {
|
|
235
|
-
params.getString("filesUrl")
|
|
236
|
-
} else {
|
|
237
|
-
null
|
|
238
|
-
}
|
|
239
|
-
if (filesUrl != null) {
|
|
240
|
-
try {
|
|
241
|
-
java.net.URL(filesUrl)
|
|
242
|
-
} catch (e: java.net.MalformedURLException) {
|
|
243
|
-
promise.rejectUpdateBundle(
|
|
244
|
-
HotUpdaterException.invalidFileUrl("filesUrl", filesUrl, UpdateFailureResource.FILE),
|
|
245
|
-
)
|
|
246
|
-
return@launch
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
val requestTimeoutMs =
|
|
250
|
-
if (params.hasKey("requestTimeout") && !params.isNull("requestTimeout")) {
|
|
251
|
-
params.getDouble("requestTimeout").toLong().takeIf { it > 0 }
|
|
252
|
-
} else {
|
|
253
|
-
null
|
|
254
|
-
} ?: HttpArtifactFileResolver.DEFAULT_TIMEOUT_MS
|
|
255
|
-
val fileResolver =
|
|
256
|
-
filesUrl?.let { HttpArtifactFileResolver(it, parseRequestHeaders(params), requestTimeoutMs) }
|
|
307
|
+
val fileResolver = planned.second
|
|
257
308
|
|
|
258
309
|
val impl = getInstance()
|
|
259
310
|
|
|
@@ -47,7 +47,14 @@ class HotUpdaterModule internal constructor(
|
|
|
47
47
|
*/
|
|
48
48
|
private fun getInstance(): HotUpdaterImpl = HotUpdater.getInstance(mReactApplicationContext)
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
/**
|
|
51
|
+
* Every changed file with its hash and URL or Hermes patch; with
|
|
52
|
+
* [requireFileHash] false, also entries that hold only the Hermes patch.
|
|
53
|
+
*/
|
|
54
|
+
private fun parseAssets(
|
|
55
|
+
params: ReadableMap,
|
|
56
|
+
requireFileHash: Boolean,
|
|
57
|
+
): Map<String, ChangedAssetDescriptor>? {
|
|
51
58
|
if (!params.hasKey("assets") || params.isNull("assets")) {
|
|
52
59
|
return null
|
|
53
60
|
}
|
|
@@ -59,39 +66,10 @@ class HotUpdaterModule internal constructor(
|
|
|
59
66
|
while (iterator.hasNextKey()) {
|
|
60
67
|
val assetPath = iterator.nextKey()
|
|
61
68
|
val assetMap = changedAssetsMap.getMap(assetPath) ?: continue
|
|
62
|
-
// In artifact protocol v2, an entry holds only the Hermes patch.
|
|
63
69
|
val assetHash = if (assetMap.hasKey("fileHash")) assetMap.getString("fileHash") else null
|
|
70
|
+
if (assetHash == null && requireFileHash) continue
|
|
64
71
|
val patchMap = assetMap.getMap("patch")
|
|
65
|
-
val patch =
|
|
66
|
-
if (patchMap != null) {
|
|
67
|
-
val algorithm = patchMap.getString("algorithm")
|
|
68
|
-
val baseBundleId = patchMap.getString("baseBundleId")
|
|
69
|
-
val baseFileHash = patchMap.getString("baseFileHash")
|
|
70
|
-
val patchFileHash = patchMap.getString("patchFileHash")
|
|
71
|
-
val patchUrl = patchMap.getString("patchUrl")
|
|
72
|
-
val byteSize = readSafeInteger(patchMap, "byteSize")
|
|
73
|
-
|
|
74
|
-
if (
|
|
75
|
-
algorithm != null &&
|
|
76
|
-
baseBundleId != null &&
|
|
77
|
-
baseFileHash != null &&
|
|
78
|
-
patchFileHash != null &&
|
|
79
|
-
patchUrl != null
|
|
80
|
-
) {
|
|
81
|
-
BsdiffPatchDescriptor(
|
|
82
|
-
algorithm = algorithm,
|
|
83
|
-
baseBundleId = baseBundleId,
|
|
84
|
-
baseFileHash = baseFileHash,
|
|
85
|
-
patchFileHash = patchFileHash,
|
|
86
|
-
patchUrl = patchUrl,
|
|
87
|
-
byteSize = byteSize,
|
|
88
|
-
)
|
|
89
|
-
} else {
|
|
90
|
-
null
|
|
91
|
-
}
|
|
92
|
-
} else {
|
|
93
|
-
null
|
|
94
|
-
}
|
|
72
|
+
val patch = parsePatch(patchMap)
|
|
95
73
|
val fileMap =
|
|
96
74
|
if (assetMap.hasKey("file") && !assetMap.isNull("file")) {
|
|
97
75
|
assetMap.getMap("file")
|
|
@@ -138,6 +116,79 @@ class HotUpdaterModule internal constructor(
|
|
|
138
116
|
return parsed
|
|
139
117
|
}
|
|
140
118
|
|
|
119
|
+
private fun parsePatch(patchMap: ReadableMap?): BsdiffPatchDescriptor? {
|
|
120
|
+
if (patchMap == null) return null
|
|
121
|
+
val algorithm = patchMap.getString("algorithm")
|
|
122
|
+
val baseBundleId = patchMap.getString("baseBundleId")
|
|
123
|
+
val baseFileHash = patchMap.getString("baseFileHash")
|
|
124
|
+
val patchFileHash = patchMap.getString("patchFileHash")
|
|
125
|
+
val patchUrl = patchMap.getString("patchUrl")
|
|
126
|
+
val byteSize = readSafeInteger(patchMap, "byteSize")
|
|
127
|
+
|
|
128
|
+
return if (
|
|
129
|
+
algorithm != null &&
|
|
130
|
+
baseBundleId != null &&
|
|
131
|
+
baseFileHash != null &&
|
|
132
|
+
patchFileHash != null &&
|
|
133
|
+
patchUrl != null
|
|
134
|
+
) {
|
|
135
|
+
BsdiffPatchDescriptor(
|
|
136
|
+
algorithm = algorithm,
|
|
137
|
+
baseBundleId = baseBundleId,
|
|
138
|
+
baseFileHash = baseFileHash,
|
|
139
|
+
patchFileHash = patchFileHash,
|
|
140
|
+
patchUrl = patchUrl,
|
|
141
|
+
byteSize = byteSize,
|
|
142
|
+
)
|
|
143
|
+
} else {
|
|
144
|
+
null
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* The resolver that asks `filesUrl` for the files native downloads one by
|
|
150
|
+
* one; null when `filesUrl` is missing.
|
|
151
|
+
*/
|
|
152
|
+
private fun parseFileResolver(params: ReadableMap): ArtifactFileResolver? {
|
|
153
|
+
val filesUrl =
|
|
154
|
+
if (params.hasKey("filesUrl") && !params.isNull("filesUrl")) {
|
|
155
|
+
params.getString("filesUrl")?.takeIf { it.isNotEmpty() }
|
|
156
|
+
} else {
|
|
157
|
+
null
|
|
158
|
+
} ?: return null
|
|
159
|
+
try {
|
|
160
|
+
java.net.URL(filesUrl)
|
|
161
|
+
} catch (e: java.net.MalformedURLException) {
|
|
162
|
+
throw HotUpdaterException.invalidFileUrl("filesUrl", filesUrl, UpdateFailureResource.FILE)
|
|
163
|
+
}
|
|
164
|
+
val requestTimeoutMs =
|
|
165
|
+
if (params.hasKey("requestTimeout") && !params.isNull("requestTimeout")) {
|
|
166
|
+
params.getDouble("requestTimeout").toLong().takeIf { it > 0 }
|
|
167
|
+
} else {
|
|
168
|
+
null
|
|
169
|
+
} ?: HttpArtifactFileResolver.DEFAULT_TIMEOUT_MS
|
|
170
|
+
return HttpArtifactFileResolver(filesUrl, parseRequestHeaders(params), requestTimeoutMs)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Artifact protocol v2: the Hermes patch as the only planned asset, and
|
|
175
|
+
* the resolver that asks `filesUrl` for the files native downloads one by
|
|
176
|
+
* one; null when `filesUrl` is missing.
|
|
177
|
+
*/
|
|
178
|
+
private fun parseArtifactInstall(params: ReadableMap): Pair<Map<String, ChangedAssetDescriptor>, ArtifactFileResolver?>? {
|
|
179
|
+
val fileResolver = parseFileResolver(params) ?: return null
|
|
180
|
+
val patchMap = if (params.hasKey("patch") && !params.isNull("patch")) params.getMap("patch") else null
|
|
181
|
+
val assetPath = patchMap?.getString("assetPath")
|
|
182
|
+
val patch = parsePatch(patchMap)
|
|
183
|
+
val assets =
|
|
184
|
+
if (assetPath != null && patch != null) {
|
|
185
|
+
mapOf(assetPath to ChangedAssetDescriptor(fileUrl = null, fileHash = "", patch = patch))
|
|
186
|
+
} else {
|
|
187
|
+
emptyMap()
|
|
188
|
+
}
|
|
189
|
+
return assets to fileResolver
|
|
190
|
+
}
|
|
191
|
+
|
|
141
192
|
private fun parseSelection(params: ReadableMap): PersistedSelection? {
|
|
142
193
|
if (!params.hasKey("selection") || params.isNull("selection")) return null
|
|
143
194
|
val selection = params.getMap("selection") ?: return null
|
|
@@ -192,6 +243,29 @@ class HotUpdaterModule internal constructor(
|
|
|
192
243
|
override fun updateBundle(
|
|
193
244
|
params: ReadableMap,
|
|
194
245
|
promise: Promise,
|
|
246
|
+
) {
|
|
247
|
+
// Legacy: artifact protocol v1, where every file comes with its URL.
|
|
248
|
+
// JavaScript from the first protocol v2 SDK also sends `filesUrl`
|
|
249
|
+
// here, with only the Hermes patch in `assets`; its OTA Bundles must
|
|
250
|
+
// still install.
|
|
251
|
+
stage(params, promise) {
|
|
252
|
+
val fileResolver = parseFileResolver(params)
|
|
253
|
+
parseAssets(params, requireFileHash = fileResolver == null)?.let { it to fileResolver }
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
@ReactMethod
|
|
258
|
+
override fun installArtifact(
|
|
259
|
+
params: ReadableMap,
|
|
260
|
+
promise: Promise,
|
|
261
|
+
) {
|
|
262
|
+
stage(params, promise) { parseArtifactInstall(params) }
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
private fun stage(
|
|
266
|
+
params: ReadableMap,
|
|
267
|
+
promise: Promise,
|
|
268
|
+
plan: () -> Pair<Map<String, ChangedAssetDescriptor>, ArtifactFileResolver?>?,
|
|
195
269
|
) {
|
|
196
270
|
moduleScope.launch {
|
|
197
271
|
try {
|
|
@@ -203,7 +277,8 @@ class HotUpdaterModule internal constructor(
|
|
|
203
277
|
|
|
204
278
|
val manifestUrl = params.getString("manifestUrl")
|
|
205
279
|
val manifestFileHash = params.getString("manifestFileHash")
|
|
206
|
-
val
|
|
280
|
+
val planned = plan()
|
|
281
|
+
val assets = planned?.first
|
|
207
282
|
if (manifestUrl.isNullOrEmpty() || manifestFileHash.isNullOrEmpty() || assets == null) {
|
|
208
283
|
promise.rejectUpdateBundle(HotUpdaterException.invalidManifestParams())
|
|
209
284
|
return@launch
|
|
@@ -234,30 +309,7 @@ class HotUpdaterModule internal constructor(
|
|
|
234
309
|
}
|
|
235
310
|
}
|
|
236
311
|
val selection = parseSelection(params)
|
|
237
|
-
val
|
|
238
|
-
if (params.hasKey("filesUrl") && !params.isNull("filesUrl")) {
|
|
239
|
-
params.getString("filesUrl")
|
|
240
|
-
} else {
|
|
241
|
-
null
|
|
242
|
-
}
|
|
243
|
-
if (filesUrl != null) {
|
|
244
|
-
try {
|
|
245
|
-
java.net.URL(filesUrl)
|
|
246
|
-
} catch (e: java.net.MalformedURLException) {
|
|
247
|
-
promise.rejectUpdateBundle(
|
|
248
|
-
HotUpdaterException.invalidFileUrl("filesUrl", filesUrl, UpdateFailureResource.FILE),
|
|
249
|
-
)
|
|
250
|
-
return@launch
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
val requestTimeoutMs =
|
|
254
|
-
if (params.hasKey("requestTimeout") && !params.isNull("requestTimeout")) {
|
|
255
|
-
params.getDouble("requestTimeout").toLong().takeIf { it > 0 }
|
|
256
|
-
} else {
|
|
257
|
-
null
|
|
258
|
-
} ?: HttpArtifactFileResolver.DEFAULT_TIMEOUT_MS
|
|
259
|
-
val fileResolver =
|
|
260
|
-
filesUrl?.let { HttpArtifactFileResolver(it, parseRequestHeaders(params), requestTimeoutMs) }
|
|
312
|
+
val fileResolver = planned.second
|
|
261
313
|
|
|
262
314
|
val impl = getInstance()
|
|
263
315
|
|
|
@@ -13,6 +13,11 @@ abstract class HotUpdaterSpec internal constructor(
|
|
|
13
13
|
promise: Promise,
|
|
14
14
|
)
|
|
15
15
|
|
|
16
|
+
abstract fun installArtifact(
|
|
17
|
+
params: ReadableMap,
|
|
18
|
+
promise: Promise,
|
|
19
|
+
)
|
|
20
|
+
|
|
16
21
|
abstract fun acceptReleaseCatalog(params: ReadableMap): Boolean
|
|
17
22
|
|
|
18
23
|
abstract fun getActiveUpdateState(): String
|
|
@@ -21,6 +21,9 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
21
21
|
- (void)updateBundle:(nullable NSDictionary *)params
|
|
22
22
|
resolver:(RCTPromiseResolveBlock)resolve
|
|
23
23
|
rejecter:(RCTPromiseRejectBlock)reject;
|
|
24
|
+
- (void)installArtifact:(nullable NSDictionary *)params
|
|
25
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
26
|
+
rejecter:(RCTPromiseRejectBlock)reject;
|
|
24
27
|
- (BOOL)acceptReleaseCatalog:(nullable NSDictionary *)params;
|
|
25
28
|
- (NSDictionary<NSString *, id> *)getActiveUpdateState;
|
|
26
29
|
- (void)getReleaseCatalogCache:(NSString *)partition
|
|
@@ -532,6 +532,7 @@ RCT_EXPORT_MODULE();
|
|
|
532
532
|
if (params.selection()) {
|
|
533
533
|
paramDict[@"selection"] = params.selection();
|
|
534
534
|
}
|
|
535
|
+
// Legacy: what JavaScript from the first artifact protocol v2 SDK sends.
|
|
535
536
|
if (params.filesUrl()) {
|
|
536
537
|
paramDict[@"filesUrl"] = params.filesUrl();
|
|
537
538
|
}
|
|
@@ -546,6 +547,46 @@ RCT_EXPORT_MODULE();
|
|
|
546
547
|
[impl updateBundle:paramDict resolver:resolve rejecter:reject];
|
|
547
548
|
}
|
|
548
549
|
|
|
550
|
+
- (void)installArtifact:(JS::NativeHotUpdater::InstallArtifactParams &)params
|
|
551
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
552
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
553
|
+
NSLog(@"[HotUpdater.mm] installArtifact called.");
|
|
554
|
+
NSMutableDictionary *paramDict = [NSMutableDictionary dictionary];
|
|
555
|
+
if (params.bundleId()) {
|
|
556
|
+
paramDict[@"bundleId"] = params.bundleId();
|
|
557
|
+
}
|
|
558
|
+
if (params.manifestUrl()) {
|
|
559
|
+
paramDict[@"manifestUrl"] = params.manifestUrl();
|
|
560
|
+
}
|
|
561
|
+
if (params.manifestFileHash()) {
|
|
562
|
+
paramDict[@"manifestFileHash"] = params.manifestFileHash();
|
|
563
|
+
}
|
|
564
|
+
if (params.archiveUrl()) {
|
|
565
|
+
paramDict[@"archiveUrl"] = params.archiveUrl();
|
|
566
|
+
}
|
|
567
|
+
if (params.patch()) {
|
|
568
|
+
paramDict[@"patch"] = params.patch();
|
|
569
|
+
}
|
|
570
|
+
if (params.filesUrl()) {
|
|
571
|
+
paramDict[@"filesUrl"] = params.filesUrl();
|
|
572
|
+
}
|
|
573
|
+
if (params.requestHeaders()) {
|
|
574
|
+
paramDict[@"requestHeaders"] = params.requestHeaders();
|
|
575
|
+
}
|
|
576
|
+
if (params.requestTimeout().has_value()) {
|
|
577
|
+
paramDict[@"requestTimeout"] = @(params.requestTimeout().value());
|
|
578
|
+
}
|
|
579
|
+
if (params.channel()) {
|
|
580
|
+
paramDict[@"channel"] = params.channel();
|
|
581
|
+
}
|
|
582
|
+
if (params.selection()) {
|
|
583
|
+
paramDict[@"selection"] = params.selection();
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
HotUpdaterImpl *impl = [HotUpdater sharedImpl];
|
|
587
|
+
[impl installArtifact:paramDict resolver:resolve rejecter:reject];
|
|
588
|
+
}
|
|
589
|
+
|
|
549
590
|
- (NSNumber *)acceptReleaseCatalog:(NSDictionary *)params {
|
|
550
591
|
return @([[HotUpdater sharedImpl] acceptReleaseCatalog:params]);
|
|
551
592
|
}
|
|
@@ -711,6 +752,14 @@ RCT_EXPORT_METHOD(updateBundle:(NSDictionary *)params
|
|
|
711
752
|
[impl updateBundle:params resolver:resolve rejecter:reject];
|
|
712
753
|
}
|
|
713
754
|
|
|
755
|
+
RCT_EXPORT_METHOD(installArtifact:(NSDictionary *)params
|
|
756
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
757
|
+
reject:(RCTPromiseRejectBlock)reject) {
|
|
758
|
+
NSLog(@"[HotUpdater.mm] installArtifact called.");
|
|
759
|
+
HotUpdaterImpl *impl = [HotUpdater sharedImpl];
|
|
760
|
+
[impl installArtifact:params resolver:resolve rejecter:reject];
|
|
761
|
+
}
|
|
762
|
+
|
|
714
763
|
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(acceptReleaseCatalog:(NSDictionary *)params) {
|
|
715
764
|
return @([[HotUpdater sharedImpl] acceptReleaseCatalog:params]);
|
|
716
765
|
}
|