@hot-updater/react-native 1.0.0-rc.14 → 1.0.0-rc.16
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/proguard-rules.pro +2 -2
- package/android/src/main/java/com/hotupdater/BuiltInAssetResolver.kt +286 -0
- package/android/src/main/java/com/hotupdater/BundleFileStorageService.kt +650 -636
- package/android/src/main/java/com/hotupdater/BundleMetadata.kt +3 -0
- package/android/src/main/java/com/hotupdater/HotUpdaterException.kt +0 -13
- package/android/src/main/java/com/hotupdater/HotUpdaterImpl.kt +10 -14
- package/android/src/main/java/com/hotupdater/OkHttpDownloadService.kt +19 -0
- package/android/src/main/java/com/hotupdater/TarArchiveInputStream.kt +214 -375
- package/android/src/main/java/com/hotupdater/TarBrArchiveExtractor.kt +119 -0
- package/android/src/newarch/HotUpdater.kt +7 -9
- package/android/src/newarch/HotUpdaterModule.kt +40 -20
- package/android/src/oldarch/HotUpdater.kt +7 -9
- package/android/src/oldarch/HotUpdaterModule.kt +40 -20
- package/android/src/test/java/com/hotupdater/BundleFileStorageServiceTest.kt +1126 -74
- package/android/src/test/java/com/hotupdater/HotUpdaterImplTest.kt +4 -5
- package/android/src/test/java/com/hotupdater/TarBrArchiveExtractorTest.kt +206 -0
- package/ios/HotUpdater/Internal/BrotliFileDecompressor.swift +167 -0
- package/ios/HotUpdater/Internal/BuiltInAssetResolver.swift +196 -0
- package/ios/HotUpdater/Internal/BundleFileStorageService.swift +773 -1016
- package/ios/HotUpdater/Internal/BundleMetadata.swift +5 -0
- package/ios/HotUpdater/Internal/FileUtilities.swift +64 -0
- package/ios/HotUpdater/Internal/HotUpdater-Bridging-Header.h +0 -1
- package/ios/HotUpdater/Internal/HotUpdater.mm +5 -27
- package/ios/HotUpdater/Internal/HotUpdaterImpl.swift +47 -31
- package/ios/HotUpdater/Internal/NotificationExtension.swift +0 -2
- package/ios/HotUpdater/Internal/TarArchiveExtractor.swift +182 -311
- package/ios/HotUpdater/Internal/URLSessionDownloadService.swift +13 -72
- package/lib/commonjs/checkForUpdate.js +7 -10
- package/lib/commonjs/checkForUpdate.js.map +1 -1
- package/lib/commonjs/checkForUpdate.releaseCatalog.spec.js +9 -4
- package/lib/commonjs/checkForUpdate.releaseCatalog.spec.js.map +1 -1
- package/lib/commonjs/error.js +4 -13
- package/lib/commonjs/error.js.map +1 -1
- package/lib/commonjs/fetchJSON.js +9 -2
- package/lib/commonjs/fetchJSON.js.map +1 -1
- package/lib/commonjs/httpClient.js +151 -39
- package/lib/commonjs/httpClient.js.map +1 -1
- package/lib/commonjs/httpClient.spec.js +247 -5
- package/lib/commonjs/httpClient.spec.js.map +1 -1
- package/lib/commonjs/index.js +15 -8
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/index.spec.js +101 -0
- package/lib/commonjs/index.spec.js.map +1 -1
- package/lib/commonjs/native.js +7 -8
- package/lib/commonjs/native.js.map +1 -1
- package/lib/commonjs/native.spec.js +21 -16
- package/lib/commonjs/native.spec.js.map +1 -1
- package/lib/commonjs/notifyAppReadyInsights.boundary.spec.js +7 -0
- package/lib/commonjs/notifyAppReadyInsights.boundary.spec.js.map +1 -1
- package/lib/commonjs/notifyAppReadyInsights.js +4 -1
- package/lib/commonjs/notifyAppReadyInsights.js.map +1 -1
- package/lib/commonjs/notifyAppReadyInsights.spec.js +59 -0
- package/lib/commonjs/notifyAppReadyInsights.spec.js.map +1 -1
- package/lib/commonjs/notifyAppReadyInsights.transport.spec.js +55 -1
- package/lib/commonjs/notifyAppReadyInsights.transport.spec.js.map +1 -1
- package/lib/commonjs/sdkVersion.js +1 -1
- package/lib/commonjs/specs/NativeHotUpdater.js.map +1 -1
- package/lib/commonjs/store.js +3 -10
- package/lib/commonjs/store.js.map +1 -1
- package/lib/commonjs/store.notification.spec.js +12 -4
- package/lib/commonjs/store.notification.spec.js.map +1 -1
- package/lib/commonjs/store.spec.js +2 -136
- package/lib/commonjs/store.spec.js.map +1 -1
- package/lib/commonjs/uuidv7.js +41 -0
- package/lib/commonjs/uuidv7.js.map +1 -0
- package/lib/commonjs/uuidv7.spec.js +30 -0
- package/lib/commonjs/uuidv7.spec.js.map +1 -0
- package/lib/commonjs/wrap.js +1 -3
- package/lib/commonjs/wrap.js.map +1 -1
- package/lib/commonjs/wrap.spec.js +7 -0
- package/lib/commonjs/wrap.spec.js.map +1 -1
- package/lib/module/checkForUpdate.js +7 -10
- package/lib/module/checkForUpdate.js.map +1 -1
- package/lib/module/checkForUpdate.releaseCatalog.spec.js +9 -4
- package/lib/module/checkForUpdate.releaseCatalog.spec.js.map +1 -1
- package/lib/module/error.js +4 -13
- package/lib/module/error.js.map +1 -1
- package/lib/module/fetchJSON.js +7 -1
- package/lib/module/fetchJSON.js.map +1 -1
- package/lib/module/httpClient.js +153 -41
- package/lib/module/httpClient.js.map +1 -1
- package/lib/module/httpClient.spec.js +248 -6
- package/lib/module/httpClient.spec.js.map +1 -1
- package/lib/module/index.js +15 -8
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.spec.js +102 -1
- package/lib/module/index.spec.js.map +1 -1
- package/lib/module/native.js +7 -8
- package/lib/module/native.js.map +1 -1
- package/lib/module/native.spec.js +21 -16
- package/lib/module/native.spec.js.map +1 -1
- package/lib/module/notifyAppReadyInsights.boundary.spec.js +7 -0
- package/lib/module/notifyAppReadyInsights.boundary.spec.js.map +1 -1
- package/lib/module/notifyAppReadyInsights.js +5 -2
- package/lib/module/notifyAppReadyInsights.js.map +1 -1
- package/lib/module/notifyAppReadyInsights.spec.js +59 -0
- package/lib/module/notifyAppReadyInsights.spec.js.map +1 -1
- package/lib/module/notifyAppReadyInsights.transport.spec.js +55 -1
- package/lib/module/notifyAppReadyInsights.transport.spec.js.map +1 -1
- package/lib/module/sdkVersion.js +1 -1
- package/lib/module/specs/NativeHotUpdater.js.map +1 -1
- package/lib/module/store.js +3 -10
- package/lib/module/store.js.map +1 -1
- package/lib/module/store.notification.spec.js +12 -4
- package/lib/module/store.notification.spec.js.map +1 -1
- package/lib/module/store.spec.js +2 -136
- package/lib/module/store.spec.js.map +1 -1
- package/lib/module/uuidv7.js +36 -0
- package/lib/module/uuidv7.js.map +1 -0
- package/lib/module/uuidv7.spec.js +30 -0
- package/lib/module/uuidv7.spec.js.map +1 -0
- package/lib/module/wrap.js +1 -3
- package/lib/module/wrap.js.map +1 -1
- package/lib/module/wrap.spec.js +7 -0
- package/lib/module/wrap.spec.js.map +1 -1
- package/lib/typescript/commonjs/checkForUpdate.d.ts +1 -2
- package/lib/typescript/commonjs/checkForUpdate.d.ts.map +1 -1
- package/lib/typescript/commonjs/error.d.ts +4 -13
- package/lib/typescript/commonjs/error.d.ts.map +1 -1
- package/lib/typescript/commonjs/fetchJSON.d.ts +4 -0
- package/lib/typescript/commonjs/fetchJSON.d.ts.map +1 -1
- package/lib/typescript/commonjs/httpClient.d.ts +6 -0
- package/lib/typescript/commonjs/httpClient.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +0 -2
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/native.d.ts +1 -6
- package/lib/typescript/commonjs/native.d.ts.map +1 -1
- package/lib/typescript/commonjs/notifyAppReadyInsights.d.ts +1 -1
- package/lib/typescript/commonjs/notifyAppReadyInsights.d.ts.map +1 -1
- package/lib/typescript/commonjs/sdkVersion.d.ts +1 -1
- package/lib/typescript/commonjs/specs/NativeHotUpdater.d.ts +8 -35
- package/lib/typescript/commonjs/specs/NativeHotUpdater.d.ts.map +1 -1
- package/lib/typescript/commonjs/store.d.ts +1 -3
- package/lib/typescript/commonjs/store.d.ts.map +1 -1
- package/lib/typescript/commonjs/uuidv7.d.ts +10 -0
- package/lib/typescript/commonjs/uuidv7.d.ts.map +1 -0
- package/lib/typescript/commonjs/wrap.d.ts.map +1 -1
- package/lib/typescript/commonjs/wrap.types.d.ts +7 -4
- package/lib/typescript/commonjs/wrap.types.d.ts.map +1 -1
- package/lib/typescript/module/checkForUpdate.d.ts +1 -2
- package/lib/typescript/module/checkForUpdate.d.ts.map +1 -1
- package/lib/typescript/module/error.d.ts +4 -13
- package/lib/typescript/module/error.d.ts.map +1 -1
- package/lib/typescript/module/fetchJSON.d.ts +4 -0
- package/lib/typescript/module/fetchJSON.d.ts.map +1 -1
- package/lib/typescript/module/httpClient.d.ts +6 -0
- package/lib/typescript/module/httpClient.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +0 -2
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/native.d.ts +1 -6
- package/lib/typescript/module/native.d.ts.map +1 -1
- package/lib/typescript/module/notifyAppReadyInsights.d.ts +1 -1
- package/lib/typescript/module/notifyAppReadyInsights.d.ts.map +1 -1
- package/lib/typescript/module/sdkVersion.d.ts +1 -1
- package/lib/typescript/module/specs/NativeHotUpdater.d.ts +8 -35
- package/lib/typescript/module/specs/NativeHotUpdater.d.ts.map +1 -1
- package/lib/typescript/module/store.d.ts +1 -3
- package/lib/typescript/module/store.d.ts.map +1 -1
- package/lib/typescript/module/uuidv7.d.ts +10 -0
- package/lib/typescript/module/uuidv7.d.ts.map +1 -0
- package/lib/typescript/module/wrap.d.ts.map +1 -1
- package/lib/typescript/module/wrap.types.d.ts +7 -4
- package/lib/typescript/module/wrap.types.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/checkForUpdate.releaseCatalog.spec.ts +10 -4
- package/src/checkForUpdate.ts +5 -11
- package/src/error.ts +4 -14
- package/src/fetchJSON.ts +12 -1
- package/src/httpClient.spec.ts +289 -8
- package/src/httpClient.ts +224 -67
- package/src/index.spec.ts +70 -1
- package/src/index.ts +18 -7
- package/src/native.spec.ts +23 -16
- package/src/native.ts +12 -24
- package/src/notifyAppReadyInsights.boundary.spec.ts +8 -0
- package/src/notifyAppReadyInsights.spec.ts +60 -0
- package/src/notifyAppReadyInsights.transport.spec.ts +66 -0
- package/src/notifyAppReadyInsights.ts +13 -1
- package/src/sdkVersion.ts +1 -1
- package/src/specs/NativeHotUpdater.ts +8 -36
- package/src/store.notification.spec.ts +13 -3
- package/src/store.spec.ts +0 -157
- package/src/store.ts +2 -23
- package/src/uuidv7.spec.ts +25 -0
- package/src/uuidv7.ts +38 -0
- package/src/wrap.spec.ts +8 -0
- package/src/wrap.tsx +0 -2
- package/src/wrap.types.ts +9 -4
- package/android/src/main/java/com/hotupdater/DecompressService.kt +0 -89
- package/android/src/main/java/com/hotupdater/DecompressionStrategy.kt +0 -26
- package/android/src/main/java/com/hotupdater/TarBrDecompressionStrategy.kt +0 -117
- package/android/src/main/java/com/hotupdater/TarGzDecompressionStrategy.kt +0 -117
- package/android/src/main/java/com/hotupdater/ZipDecompressionStrategy.kt +0 -192
- package/android/src/test/java/com/hotupdater/TarArchiveInputStreamTest.kt +0 -68
- package/ios/HotUpdater/Internal/ArchiveExtractionUtilities.swift +0 -178
- package/ios/HotUpdater/Internal/DecompressService.swift +0 -112
- package/ios/HotUpdater/Internal/DecompressionStrategy.swift +0 -22
- package/ios/HotUpdater/Internal/StreamingTarArchiveExtractor.swift +0 -370
- package/ios/HotUpdater/Internal/TarBrDecompressionStrategy.swift +0 -39
- package/ios/HotUpdater/Internal/TarGzDecompressionStrategy.swift +0 -59
- package/ios/HotUpdater/Internal/ZipArchiveExtractor.swift +0 -482
- package/ios/HotUpdater/Internal/ZipDecompressionStrategy.swift +0 -56
|
@@ -84,6 +84,7 @@ public struct BundleMetadata: Codable {
|
|
|
84
84
|
var stableSelection: PersistedSelection?
|
|
85
85
|
var stagingSelection: PersistedSelection?
|
|
86
86
|
var verificationPending: Bool
|
|
87
|
+
var launchInProgress: Bool
|
|
87
88
|
var pendingTransition: PendingBundleTransition?
|
|
88
89
|
var pendingSelectionTransition: PendingSelectionTransition?
|
|
89
90
|
var highestSeenCatalogs: [String: CatalogHighWater]
|
|
@@ -98,6 +99,7 @@ public struct BundleMetadata: Codable {
|
|
|
98
99
|
case stableSelection = "stable_selection"
|
|
99
100
|
case stagingSelection = "staging_selection"
|
|
100
101
|
case verificationPending = "verification_pending"
|
|
102
|
+
case launchInProgress = "launch_in_progress"
|
|
101
103
|
case pendingTransition = "pending_transition"
|
|
102
104
|
case pendingSelectionTransition = "pending_selection_transition"
|
|
103
105
|
case highestSeenCatalogs = "highest_seen_catalogs"
|
|
@@ -113,6 +115,7 @@ public struct BundleMetadata: Codable {
|
|
|
113
115
|
stableSelection: PersistedSelection? = nil,
|
|
114
116
|
stagingSelection: PersistedSelection? = nil,
|
|
115
117
|
verificationPending: Bool = false,
|
|
118
|
+
launchInProgress: Bool = false,
|
|
116
119
|
pendingTransition: PendingBundleTransition? = nil,
|
|
117
120
|
pendingSelectionTransition: PendingSelectionTransition? = nil,
|
|
118
121
|
highestSeenCatalogs: [String: CatalogHighWater] = [:],
|
|
@@ -126,6 +129,7 @@ public struct BundleMetadata: Codable {
|
|
|
126
129
|
self.stableSelection = stableSelection
|
|
127
130
|
self.stagingSelection = stagingSelection
|
|
128
131
|
self.verificationPending = verificationPending
|
|
132
|
+
self.launchInProgress = launchInProgress
|
|
129
133
|
self.pendingTransition = pendingTransition
|
|
130
134
|
self.pendingSelectionTransition = pendingSelectionTransition
|
|
131
135
|
self.highestSeenCatalogs = highestSeenCatalogs
|
|
@@ -144,6 +148,7 @@ public struct BundleMetadata: Codable {
|
|
|
144
148
|
stagingSelection = try values.decodeIfPresent(PersistedSelection.self, forKey: .stagingSelection)
|
|
145
149
|
?? stagingBundleId.map(PersistedSelection.legacyBundle)
|
|
146
150
|
verificationPending = try values.decodeIfPresent(Bool.self, forKey: .verificationPending) ?? false
|
|
151
|
+
launchInProgress = try values.decodeIfPresent(Bool.self, forKey: .launchInProgress) ?? false
|
|
147
152
|
pendingTransition = try values.decodeIfPresent(PendingBundleTransition.self, forKey: .pendingTransition)
|
|
148
153
|
pendingSelectionTransition = try values.decodeIfPresent(PendingSelectionTransition.self, forKey: .pendingSelectionTransition)
|
|
149
154
|
highestSeenCatalogs = try values.decodeIfPresent([String: CatalogHighWater].self, forKey: .highestSeenCatalogs) ?? [:]
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
enum FileUtilities {
|
|
4
|
+
static func readUpToCount(from handle: FileHandle, count: Int) throws -> Data? {
|
|
5
|
+
guard count >= 0 else {
|
|
6
|
+
throw NSError(
|
|
7
|
+
domain: "FileUtilities",
|
|
8
|
+
code: 1,
|
|
9
|
+
userInfo: [NSLocalizedDescriptionKey: "Invalid read size: \(count)"]
|
|
10
|
+
)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if count == 0 {
|
|
14
|
+
return Data()
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if #available(macOS 10.15.4, iOS 13.4, watchOS 6.2, tvOS 13.4, *) {
|
|
18
|
+
return try handle.read(upToCount: count)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return handle.readData(ofLength: count)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
static func normalizedRelativePath(from rawPath: String) -> String? {
|
|
25
|
+
let candidate = rawPath.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
26
|
+
guard !candidate.isEmpty,
|
|
27
|
+
!candidate.contains("\0"),
|
|
28
|
+
!candidate.contains("\\"),
|
|
29
|
+
!candidate.hasPrefix("/"),
|
|
30
|
+
candidate.range(of: #"^[A-Za-z]:"#, options: .regularExpression) == nil
|
|
31
|
+
else {
|
|
32
|
+
return nil
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
let components = candidate.split(separator: "/").map(String.init)
|
|
36
|
+
guard !components.isEmpty,
|
|
37
|
+
components.count == candidate.split(separator: "/", omittingEmptySubsequences: false).count,
|
|
38
|
+
!components.contains(".."),
|
|
39
|
+
!components.contains(".")
|
|
40
|
+
else {
|
|
41
|
+
return nil
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return components.joined(separator: "/")
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
static func fileURL(for relativePath: String, destinationRoot: String) throws -> URL {
|
|
48
|
+
let rootURL = URL(fileURLWithPath: destinationRoot, isDirectory: true)
|
|
49
|
+
let targetURL = rootURL.appendingPathComponent(relativePath)
|
|
50
|
+
let standardizedRoot = rootURL.standardizedFileURL.path
|
|
51
|
+
let standardizedTarget = targetURL.standardizedFileURL.path
|
|
52
|
+
|
|
53
|
+
guard standardizedTarget == standardizedRoot ||
|
|
54
|
+
standardizedTarget.hasPrefix(standardizedRoot + "/") else {
|
|
55
|
+
throw NSError(
|
|
56
|
+
domain: "FileUtilities",
|
|
57
|
+
code: 2,
|
|
58
|
+
userInfo: [NSLocalizedDescriptionKey: "Path traversal attempt detected: \(relativePath)"]
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return targetURL
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
#import "React/RCTConstants.h"
|
|
8
8
|
#import "React/RCTRootView.h"
|
|
9
9
|
#import "React/RCTUtils.h" // Needed for RCTPromiseResolveBlock/RejectBlock in Swift
|
|
10
|
-
#import <SSZipArchive/SSZipArchive.h>
|
|
11
10
|
#import "BsdiffPatchBridge.h"
|
|
12
11
|
|
|
13
12
|
@interface HotUpdaterRecoverySignalBridge : NSObject
|
|
@@ -274,8 +274,6 @@ extern "C" void *HotUpdaterCopyMinBundleId(void)
|
|
|
274
274
|
|
|
275
275
|
|
|
276
276
|
// Define Notification names used for observing Swift Core
|
|
277
|
-
NSNotificationName const HotUpdaterDownloadProgressUpdateNotification = @"HotUpdaterDownloadProgressUpdate";
|
|
278
|
-
NSNotificationName const HotUpdaterDownloadDidFinishNotification = @"HotUpdaterDownloadDidFinish";
|
|
279
277
|
NSNotificationName const HotUpdaterUpdateProgressDidChangeNotification = @"HotUpdaterUpdateProgressDidChange";
|
|
280
278
|
|
|
281
279
|
@interface HotUpdaterRecoverySignalBridge : NSObject
|
|
@@ -300,8 +298,6 @@ NSNotificationName const HotUpdaterUpdateProgressDidChangeNotification = @"HotUp
|
|
|
300
298
|
|
|
301
299
|
@implementation HotUpdater {
|
|
302
300
|
bool hasListeners;
|
|
303
|
-
// Keep track of tasks ONLY for removing observers when this ObjC instance is invalidated
|
|
304
|
-
NSMutableSet<NSURLSessionTask *> *observedTasks; // Changed to NSURLSessionTask for broader compatibility if needed
|
|
305
301
|
}
|
|
306
302
|
|
|
307
303
|
@synthesize bridge = _bridge;
|
|
@@ -314,16 +310,10 @@ NSNotificationName const HotUpdaterUpdateProgressDidChangeNotification = @"HotUp
|
|
|
314
310
|
- (instancetype)init {
|
|
315
311
|
self = [super init];
|
|
316
312
|
if (self) {
|
|
317
|
-
observedTasks = [NSMutableSet set];
|
|
318
|
-
|
|
319
313
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
320
314
|
selector:@selector(handleDownloadProgress:)
|
|
321
315
|
name:HotUpdaterUpdateProgressDidChangeNotification
|
|
322
316
|
object:nil];
|
|
323
|
-
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
324
|
-
selector:@selector(handleDownloadCompletion:)
|
|
325
|
-
name:HotUpdaterDownloadDidFinishNotification
|
|
326
|
-
object:nil];
|
|
327
317
|
|
|
328
318
|
_lastUpdateTime = 0;
|
|
329
319
|
}
|
|
@@ -349,7 +339,6 @@ NSNotificationName const HotUpdaterUpdateProgressDidChangeNotification = @"HotUp
|
|
|
349
339
|
if (gHotUpdaterBridge == self.bridge) {
|
|
350
340
|
gHotUpdaterBridge = nil;
|
|
351
341
|
}
|
|
352
|
-
// Swift side should handle KVO observer removal for its tasks
|
|
353
342
|
[super invalidate];
|
|
354
343
|
}
|
|
355
344
|
|
|
@@ -520,14 +509,6 @@ RCT_EXPORT_MODULE();
|
|
|
520
509
|
}
|
|
521
510
|
}
|
|
522
511
|
|
|
523
|
-
- (void)handleDownloadCompletion:(NSNotification *)notification {
|
|
524
|
-
NSURLSessionTask *task = notification.object; // Task that finished
|
|
525
|
-
RCTLogInfo(@"[HotUpdater.mm] Received download completion notification for task: %@", task.originalRequest.URL);
|
|
526
|
-
// Swift side handles KVO observer removal internally now when task finishes.
|
|
527
|
-
// No specific cleanup needed here based on this notification anymore.
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
|
|
531
512
|
#pragma mark - React Native Events (Keep as is)
|
|
532
513
|
|
|
533
514
|
- (NSArray<NSString *> *)supportedEvents {
|
|
@@ -594,20 +575,17 @@ RCT_EXPORT_MODULE();
|
|
|
594
575
|
if (params.bundleId()) {
|
|
595
576
|
paramDict[@"bundleId"] = params.bundleId();
|
|
596
577
|
}
|
|
597
|
-
if (params.fileUrl()) {
|
|
598
|
-
paramDict[@"fileUrl"] = params.fileUrl();
|
|
599
|
-
}
|
|
600
|
-
if (params.fileHash()) {
|
|
601
|
-
paramDict[@"fileHash"] = params.fileHash();
|
|
602
|
-
}
|
|
603
578
|
if (params.manifestUrl()) {
|
|
604
579
|
paramDict[@"manifestUrl"] = params.manifestUrl();
|
|
605
580
|
}
|
|
606
581
|
if (params.manifestFileHash()) {
|
|
607
582
|
paramDict[@"manifestFileHash"] = params.manifestFileHash();
|
|
608
583
|
}
|
|
609
|
-
if (params.
|
|
610
|
-
paramDict[@"
|
|
584
|
+
if (params.archiveUrl()) {
|
|
585
|
+
paramDict[@"archiveUrl"] = params.archiveUrl();
|
|
586
|
+
}
|
|
587
|
+
if (params.assets()) {
|
|
588
|
+
paramDict[@"assets"] = params.assets();
|
|
611
589
|
}
|
|
612
590
|
if (params.channel()) {
|
|
613
591
|
paramDict[@"channel"] = params.channel();
|
|
@@ -61,6 +61,21 @@ private func hotUpdaterGetMinBundleId() -> String {
|
|
|
61
61
|
private static let DEFAULT_CHANNEL = "production"
|
|
62
62
|
private static let CHANNEL_STORAGE_KEY = "HotUpdaterChannel"
|
|
63
63
|
|
|
64
|
+
private static func parseSafeByteSize(_ value: Any?) -> Int64? {
|
|
65
|
+
guard let number = value as? NSNumber,
|
|
66
|
+
String(cString: number.objCType) != "c" else {
|
|
67
|
+
return nil
|
|
68
|
+
}
|
|
69
|
+
let doubleValue = number.doubleValue
|
|
70
|
+
guard doubleValue.isFinite,
|
|
71
|
+
doubleValue >= 0,
|
|
72
|
+
doubleValue <= 9_007_199_254_740_991,
|
|
73
|
+
doubleValue.rounded(.towardZero) == doubleValue else {
|
|
74
|
+
return nil
|
|
75
|
+
}
|
|
76
|
+
return Int64(doubleValue)
|
|
77
|
+
}
|
|
78
|
+
|
|
64
79
|
// MARK: - Initialization
|
|
65
80
|
|
|
66
81
|
/**
|
|
@@ -71,12 +86,9 @@ private func hotUpdaterGetMinBundleId() -> String {
|
|
|
71
86
|
let isolationKey = HotUpdaterImpl.getIsolationKey()
|
|
72
87
|
let preferences = VersionedPreferencesService()
|
|
73
88
|
let downloadService = URLSessionDownloadService()
|
|
74
|
-
let decompressService = DecompressService()
|
|
75
|
-
|
|
76
89
|
let bundleStorage = BundleFileStorageService(
|
|
77
90
|
fileSystem: fileSystem,
|
|
78
91
|
downloadService: downloadService,
|
|
79
|
-
decompressService: decompressService,
|
|
80
92
|
preferences: preferences,
|
|
81
93
|
isolationKey: isolationKey,
|
|
82
94
|
builtInBundleIdProvider: { HotUpdaterImpl.minBundleId() }
|
|
@@ -231,7 +243,7 @@ private func hotUpdaterGetMinBundleId() -> String {
|
|
|
231
243
|
/**
|
|
232
244
|
* Updates the bundle from JavaScript bridge.
|
|
233
245
|
* This method acts as the primary error boundary for all bundle operations.
|
|
234
|
-
* @param params Dictionary with bundleId and
|
|
246
|
+
* @param params Dictionary with bundleId, manifest, and asset parameters
|
|
235
247
|
* @param resolve Promise resolve callback
|
|
236
248
|
* @param reject Promise reject callback
|
|
237
249
|
*/
|
|
@@ -255,36 +267,40 @@ private func hotUpdaterGetMinBundleId() -> String {
|
|
|
255
267
|
return
|
|
256
268
|
}
|
|
257
269
|
|
|
258
|
-
let
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
userInfo: [NSLocalizedDescriptionKey: "Invalid 'fileUrl' provided: \(fileUrlString)"])
|
|
265
|
-
reject("INVALID_FILE_URL", error.localizedDescription, error)
|
|
266
|
-
return
|
|
267
|
-
}
|
|
268
|
-
fileUrl = url
|
|
270
|
+
guard let manifestFileHash = data["manifestFileHash"] as? String,
|
|
271
|
+
!manifestFileHash.isEmpty else {
|
|
272
|
+
let error = NSError(domain: "HotUpdater", code: 0,
|
|
273
|
+
userInfo: [NSLocalizedDescriptionKey: "Missing manifest file hash"])
|
|
274
|
+
reject("INVALID_MANIFEST", error.localizedDescription, error)
|
|
275
|
+
return
|
|
269
276
|
}
|
|
270
|
-
|
|
271
|
-
// Extract fileHash if provided
|
|
272
|
-
let fileHash = data["fileHash"] as? String
|
|
273
|
-
let manifestFileHash = data["manifestFileHash"] as? String
|
|
274
277
|
let channel = data["channel"] as? String
|
|
275
278
|
let manifestUrlString = data["manifestUrl"] as? String ?? ""
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
+
guard let manifestUrl = URL(string: manifestUrlString) else {
|
|
280
|
+
let error = NSError(domain: "HotUpdater", code: 0,
|
|
281
|
+
userInfo: [NSLocalizedDescriptionKey: "Invalid 'manifestUrl' provided: \(manifestUrlString)"])
|
|
282
|
+
reject("INVALID_FILE_URL", error.localizedDescription, error)
|
|
283
|
+
return
|
|
284
|
+
}
|
|
285
|
+
let archiveUrl: URL?
|
|
286
|
+
if let archiveUrlString = data["archiveUrl"] as? String {
|
|
287
|
+
guard let parsedArchiveUrl = URL(string: archiveUrlString) else {
|
|
279
288
|
let error = NSError(domain: "HotUpdater", code: 0,
|
|
280
|
-
userInfo: [NSLocalizedDescriptionKey: "Invalid '
|
|
289
|
+
userInfo: [NSLocalizedDescriptionKey: "Invalid 'archiveUrl' provided: \(archiveUrlString)"])
|
|
281
290
|
reject("INVALID_FILE_URL", error.localizedDescription, error)
|
|
282
291
|
return
|
|
283
292
|
}
|
|
284
|
-
|
|
293
|
+
archiveUrl = parsedArchiveUrl
|
|
294
|
+
} else {
|
|
295
|
+
archiveUrl = nil
|
|
296
|
+
}
|
|
297
|
+
guard let assetsPayload = data["assets"] as? [String: [String: Any]] else {
|
|
298
|
+
let error = NSError(domain: "HotUpdater", code: 0,
|
|
299
|
+
userInfo: [NSLocalizedDescriptionKey: "Missing manifest assets"])
|
|
300
|
+
reject("INVALID_MANIFEST", error.localizedDescription, error)
|
|
301
|
+
return
|
|
285
302
|
}
|
|
286
|
-
let
|
|
287
|
-
let changedAssets = changedAssetsPayload?.reduce(into: [String: ChangedAssetDescriptor]()) { partialResult, entry in
|
|
303
|
+
let assets = assetsPayload.reduce(into: [String: ChangedAssetDescriptor]()) { partialResult, entry in
|
|
288
304
|
guard let fileHash = entry.value["fileHash"] as? String,
|
|
289
305
|
!fileHash.isEmpty
|
|
290
306
|
else {
|
|
@@ -308,7 +324,8 @@ private func hotUpdaterGetMinBundleId() -> String {
|
|
|
308
324
|
baseBundleId: baseBundleId,
|
|
309
325
|
baseFileHash: baseFileHash,
|
|
310
326
|
patchFileHash: patchFileHash,
|
|
311
|
-
patchUrl: patchUrl
|
|
327
|
+
patchUrl: patchUrl,
|
|
328
|
+
byteSize: Self.parseSafeByteSize(payload["byteSize"])
|
|
312
329
|
)
|
|
313
330
|
}
|
|
314
331
|
let filePayload = entry.value["file"] as? [String: Any]
|
|
@@ -339,10 +356,10 @@ private func hotUpdaterGetMinBundleId() -> String {
|
|
|
339
356
|
// Extract progress callback if provided
|
|
340
357
|
let progressCallback = data["progressCallback"] as? RCTResponseSenderBlock
|
|
341
358
|
|
|
342
|
-
NSLog("[HotUpdaterImpl] updateBundle called with bundleId: \(bundleId),
|
|
359
|
+
NSLog("[HotUpdaterImpl] updateBundle called with bundleId: \(bundleId), manifestUrl: \(manifestUrl.absoluteString)")
|
|
343
360
|
|
|
344
361
|
// Heavy work is delegated to bundle storage service with safe error handling
|
|
345
|
-
bundleStorage.updateBundle(bundleId: bundleId,
|
|
362
|
+
bundleStorage.updateBundle(bundleId: bundleId, manifestUrl: manifestUrl, manifestFileHash: manifestFileHash, archiveUrl: archiveUrl, assets: assets, progressHandler: { payload in
|
|
346
363
|
DispatchQueue.main.async {
|
|
347
364
|
NotificationCenter.default.post(
|
|
348
365
|
name: .updateProgressDidChange,
|
|
@@ -544,7 +561,6 @@ private func hotUpdaterGetMinBundleId() -> String {
|
|
|
544
561
|
"DIRECTORY_CREATION_FAILED",
|
|
545
562
|
"DOWNLOAD_FAILED",
|
|
546
563
|
"INCOMPLETE_DOWNLOAD",
|
|
547
|
-
"EXTRACTION_FORMAT_ERROR",
|
|
548
564
|
"INVALID_BUNDLE",
|
|
549
565
|
"INSUFFICIENT_DISK_SPACE",
|
|
550
566
|
"SIGNATURE_VERIFICATION_FAILED",
|
|
@@ -614,7 +630,7 @@ private func hotUpdaterGetMinBundleId() -> String {
|
|
|
614
630
|
|
|
615
631
|
/**
|
|
616
632
|
* Gets the current active bundle ID from bundle storage.
|
|
617
|
-
* Reads
|
|
633
|
+
* Reads the required OTA manifest.json.
|
|
618
634
|
* Built-in bundle fallback is handled in JS.
|
|
619
635
|
*/
|
|
620
636
|
public func getBundleId() -> String? {
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import Foundation
|
|
2
2
|
|
|
3
3
|
extension Notification.Name {
|
|
4
|
-
static let downloadProgressUpdate = Notification.Name("HotUpdaterDownloadProgressUpdate")
|
|
5
|
-
static let downloadDidFinish = Notification.Name("HotUpdaterDownloadDidFinish")
|
|
6
4
|
static let updateProgressDidChange = Notification.Name("HotUpdaterUpdateProgressDidChange")
|
|
7
5
|
}
|