@hot-updater/react-native 0.36.7 → 1.0.0-rc.1
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/main/java/com/hotupdater/BundleFileStorageService.kt +357 -6
- package/android/src/main/java/com/hotupdater/BundleMetadata.kt +268 -34
- package/android/src/main/java/com/hotupdater/HotUpdaterImpl.kt +75 -9
- package/android/src/main/java/com/hotupdater/NativeConfigUtils.kt +2 -16
- package/android/src/main/java/com/hotupdater/ReleaseCatalogCacheService.kt +166 -0
- package/android/src/main/java/com/hotupdater/SignatureVerifier.kt +1 -2
- package/android/src/newarch/HotUpdater.kt +1 -1
- package/android/src/newarch/HotUpdaterModule.kt +116 -0
- package/android/src/oldarch/HotUpdater.kt +1 -1
- package/android/src/oldarch/HotUpdaterModule.kt +128 -0
- package/android/src/oldarch/HotUpdaterSpec.kt +38 -0
- package/android/src/test/java/com/hotupdater/BundleFileStorageServiceTest.kt +280 -2
- package/android/src/test/java/com/hotupdater/HotUpdaterImplTest.kt +57 -2
- package/android/src/test/java/com/hotupdater/ReleaseCatalogCacheServiceTest.kt +118 -0
- package/ios/HotUpdater/Internal/BundleFileStorageService.swift +491 -30
- package/ios/HotUpdater/Internal/BundleMetadata.swift +229 -6
- package/ios/HotUpdater/Internal/HotUpdater.mm +122 -0
- package/ios/HotUpdater/Internal/HotUpdaterImpl.swift +176 -7
- package/ios/HotUpdater/Internal/ReleaseCatalogCacheService.swift +213 -0
- package/lib/commonjs/catalogCacheNative.js +44 -0
- package/lib/commonjs/catalogCacheNative.js.map +1 -0
- package/lib/commonjs/catalogCacheNative.spec.js +31 -0
- package/lib/commonjs/catalogCacheNative.spec.js.map +1 -0
- package/lib/commonjs/checkForUpdate.js +231 -60
- package/lib/commonjs/checkForUpdate.js.map +1 -1
- package/lib/commonjs/checkForUpdate.releaseCatalog.spec.js +604 -0
- package/lib/commonjs/checkForUpdate.releaseCatalog.spec.js.map +1 -0
- package/lib/commonjs/error.js +8 -1
- package/lib/commonjs/error.js.map +1 -1
- package/lib/commonjs/{fetchUpdateInfo.js → fetchJSON.js} +11 -14
- package/lib/commonjs/fetchJSON.js.map +1 -0
- package/lib/commonjs/httpClient.js +153 -0
- package/lib/commonjs/httpClient.js.map +1 -0
- package/lib/commonjs/httpClient.spec.js +102 -0
- package/lib/commonjs/httpClient.spec.js.map +1 -0
- package/lib/commonjs/index.js +47 -70
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/index.spec.js +115 -159
- package/lib/commonjs/index.spec.js.map +1 -1
- package/lib/commonjs/iosInterop.spec.js +18 -0
- package/lib/commonjs/iosInterop.spec.js.map +1 -0
- package/lib/commonjs/native.js +222 -53
- package/lib/commonjs/native.js.map +1 -1
- package/lib/commonjs/native.spec.js +226 -12
- package/lib/commonjs/native.spec.js.map +1 -1
- package/lib/commonjs/notifyAppReadyAnalytics.boundary.spec.js +218 -0
- package/lib/commonjs/notifyAppReadyAnalytics.boundary.spec.js.map +1 -0
- package/lib/commonjs/notifyAppReadyAnalytics.js +133 -0
- package/lib/commonjs/notifyAppReadyAnalytics.js.map +1 -0
- package/lib/commonjs/notifyAppReadyAnalytics.spec.js +246 -0
- package/lib/commonjs/notifyAppReadyAnalytics.spec.js.map +1 -0
- package/lib/commonjs/notifyAppReadyAnalytics.test-utils.js +24 -0
- package/lib/commonjs/notifyAppReadyAnalytics.test-utils.js.map +1 -0
- package/lib/commonjs/notifyAppReadyAnalytics.transport.spec.js +117 -0
- package/lib/commonjs/notifyAppReadyAnalytics.transport.spec.js.map +1 -0
- package/lib/commonjs/releaseCatalogCache.js +179 -0
- package/lib/commonjs/releaseCatalogCache.js.map +1 -0
- package/lib/commonjs/releaseCatalogCache.spec.js +195 -0
- package/lib/commonjs/releaseCatalogCache.spec.js.map +1 -0
- package/lib/commonjs/releaseCatalogCacheNativeContract.spec.js +64 -0
- package/lib/commonjs/releaseCatalogCacheNativeContract.spec.js.map +1 -0
- package/lib/commonjs/sdkVersion.js +1 -1
- package/lib/commonjs/sdkVersion.js.map +1 -1
- package/lib/commonjs/specs/NativeHotUpdater.js.map +1 -1
- package/lib/commonjs/types.js +0 -12
- package/lib/commonjs/types.js.map +1 -1
- package/lib/commonjs/wrap.js +7 -82
- package/lib/commonjs/wrap.js.map +1 -1
- package/lib/commonjs/wrap.spec.js +203 -56
- package/lib/commonjs/wrap.spec.js.map +1 -1
- package/lib/commonjs/wrap.types.js +6 -0
- package/lib/commonjs/wrap.types.js.map +1 -0
- package/lib/module/catalogCacheNative.js +36 -0
- package/lib/module/catalogCacheNative.js.map +1 -0
- package/lib/module/catalogCacheNative.spec.js +31 -0
- package/lib/module/catalogCacheNative.spec.js.map +1 -0
- package/lib/module/checkForUpdate.js +233 -62
- package/lib/module/checkForUpdate.js.map +1 -1
- package/lib/module/checkForUpdate.releaseCatalog.spec.js +603 -0
- package/lib/module/checkForUpdate.releaseCatalog.spec.js.map +1 -0
- package/lib/module/error.js +6 -0
- package/lib/module/error.js.map +1 -1
- package/lib/module/{fetchUpdateInfo.js → fetchJSON.js} +9 -12
- package/lib/module/fetchJSON.js.map +1 -0
- package/lib/module/httpClient.js +148 -0
- package/lib/module/httpClient.js.map +1 -0
- package/lib/module/httpClient.spec.js +102 -0
- package/lib/module/httpClient.spec.js.map +1 -0
- package/lib/module/index.js +48 -65
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.spec.js +115 -159
- package/lib/module/index.spec.js.map +1 -1
- package/lib/module/iosInterop.spec.js +18 -0
- package/lib/module/iosInterop.spec.js.map +1 -0
- package/lib/module/native.js +206 -49
- package/lib/module/native.js.map +1 -1
- package/lib/module/native.spec.js +226 -12
- package/lib/module/native.spec.js.map +1 -1
- package/lib/module/notifyAppReadyAnalytics.boundary.spec.js +217 -0
- package/lib/module/notifyAppReadyAnalytics.boundary.spec.js.map +1 -0
- package/lib/module/notifyAppReadyAnalytics.js +128 -0
- package/lib/module/notifyAppReadyAnalytics.js.map +1 -0
- package/lib/module/notifyAppReadyAnalytics.spec.js +245 -0
- package/lib/module/notifyAppReadyAnalytics.spec.js.map +1 -0
- package/lib/module/notifyAppReadyAnalytics.test-utils.js +18 -0
- package/lib/module/notifyAppReadyAnalytics.test-utils.js.map +1 -0
- package/lib/module/notifyAppReadyAnalytics.transport.spec.js +116 -0
- package/lib/module/notifyAppReadyAnalytics.transport.spec.js.map +1 -0
- package/lib/module/releaseCatalogCache.js +171 -0
- package/lib/module/releaseCatalogCache.js.map +1 -0
- package/lib/module/releaseCatalogCache.spec.js +195 -0
- package/lib/module/releaseCatalogCache.spec.js.map +1 -0
- package/lib/module/releaseCatalogCacheNativeContract.spec.js +64 -0
- package/lib/module/releaseCatalogCacheNativeContract.spec.js.map +1 -0
- package/lib/module/sdkVersion.js +1 -1
- package/lib/module/sdkVersion.js.map +1 -1
- package/lib/module/specs/NativeHotUpdater.js.map +1 -1
- package/lib/module/types.js +0 -12
- package/lib/module/types.js.map +1 -1
- package/lib/module/wrap.js +6 -81
- package/lib/module/wrap.js.map +1 -1
- package/lib/module/wrap.spec.js +203 -56
- package/lib/module/wrap.spec.js.map +1 -1
- package/lib/module/wrap.types.js +4 -0
- package/lib/module/wrap.types.js.map +1 -0
- package/lib/typescript/commonjs/catalogCacheNative.d.ts +4 -0
- package/lib/typescript/commonjs/catalogCacheNative.d.ts.map +1 -0
- package/lib/typescript/commonjs/checkForUpdate.d.ts +14 -4
- package/lib/typescript/commonjs/checkForUpdate.d.ts.map +1 -1
- package/lib/typescript/commonjs/error.d.ts +3 -0
- package/lib/typescript/commonjs/error.d.ts.map +1 -1
- package/lib/typescript/commonjs/fetchJSON.d.ts +6 -0
- package/lib/typescript/commonjs/fetchJSON.d.ts.map +1 -0
- package/lib/typescript/commonjs/httpClient.d.ts +56 -0
- package/lib/typescript/commonjs/httpClient.d.ts.map +1 -0
- package/lib/typescript/commonjs/index.d.ts +31 -40
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/native.d.ts +84 -17
- package/lib/typescript/commonjs/native.d.ts.map +1 -1
- package/lib/typescript/commonjs/notifyAppReadyAnalytics.d.ts +13 -0
- package/lib/typescript/commonjs/notifyAppReadyAnalytics.d.ts.map +1 -0
- package/lib/typescript/commonjs/notifyAppReadyAnalytics.test-utils.d.ts +8 -0
- package/lib/typescript/commonjs/notifyAppReadyAnalytics.test-utils.d.ts.map +1 -0
- package/lib/typescript/commonjs/releaseCatalogCache.d.ts +25 -0
- package/lib/typescript/commonjs/releaseCatalogCache.d.ts.map +1 -0
- package/lib/typescript/commonjs/sdkVersion.d.ts +1 -1
- package/lib/typescript/commonjs/sdkVersion.d.ts.map +1 -1
- package/lib/typescript/commonjs/specs/NativeHotUpdater.d.ts +40 -5
- package/lib/typescript/commonjs/specs/NativeHotUpdater.d.ts.map +1 -1
- package/lib/typescript/commonjs/types.d.ts +0 -118
- package/lib/typescript/commonjs/types.d.ts.map +1 -1
- package/lib/typescript/commonjs/wrap.d.ts +2 -191
- package/lib/typescript/commonjs/wrap.d.ts.map +1 -1
- package/lib/typescript/commonjs/wrap.types.d.ts +65 -0
- package/lib/typescript/commonjs/wrap.types.d.ts.map +1 -0
- package/lib/typescript/module/catalogCacheNative.d.ts +4 -0
- package/lib/typescript/module/catalogCacheNative.d.ts.map +1 -0
- package/lib/typescript/module/checkForUpdate.d.ts +14 -4
- package/lib/typescript/module/checkForUpdate.d.ts.map +1 -1
- package/lib/typescript/module/error.d.ts +3 -0
- package/lib/typescript/module/error.d.ts.map +1 -1
- package/lib/typescript/module/fetchJSON.d.ts +6 -0
- package/lib/typescript/module/fetchJSON.d.ts.map +1 -0
- package/lib/typescript/module/httpClient.d.ts +56 -0
- package/lib/typescript/module/httpClient.d.ts.map +1 -0
- package/lib/typescript/module/index.d.ts +31 -40
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/native.d.ts +84 -17
- package/lib/typescript/module/native.d.ts.map +1 -1
- package/lib/typescript/module/notifyAppReadyAnalytics.d.ts +13 -0
- package/lib/typescript/module/notifyAppReadyAnalytics.d.ts.map +1 -0
- package/lib/typescript/module/notifyAppReadyAnalytics.test-utils.d.ts +8 -0
- package/lib/typescript/module/notifyAppReadyAnalytics.test-utils.d.ts.map +1 -0
- package/lib/typescript/module/releaseCatalogCache.d.ts +25 -0
- package/lib/typescript/module/releaseCatalogCache.d.ts.map +1 -0
- package/lib/typescript/module/sdkVersion.d.ts +1 -1
- package/lib/typescript/module/sdkVersion.d.ts.map +1 -1
- package/lib/typescript/module/specs/NativeHotUpdater.d.ts +40 -5
- package/lib/typescript/module/specs/NativeHotUpdater.d.ts.map +1 -1
- package/lib/typescript/module/types.d.ts +0 -118
- package/lib/typescript/module/types.d.ts.map +1 -1
- package/lib/typescript/module/wrap.d.ts +2 -191
- package/lib/typescript/module/wrap.d.ts.map +1 -1
- package/lib/typescript/module/wrap.types.d.ts +65 -0
- package/lib/typescript/module/wrap.types.d.ts.map +1 -0
- package/package.json +6 -24
- package/src/catalogCacheNative.spec.ts +63 -0
- package/src/catalogCacheNative.ts +74 -0
- package/src/checkForUpdate.releaseCatalog.spec.ts +596 -0
- package/src/checkForUpdate.ts +367 -96
- package/src/error.ts +7 -0
- package/src/{fetchUpdateInfo.ts → fetchJSON.ts} +8 -15
- package/src/httpClient.spec.ts +132 -0
- package/src/httpClient.ts +261 -0
- package/src/index.spec.ts +108 -201
- package/src/index.ts +68 -91
- package/src/iosInterop.spec.ts +30 -0
- package/src/native.spec.ts +226 -10
- package/src/native.ts +385 -81
- package/src/notifyAppReadyAnalytics.boundary.spec.ts +234 -0
- package/src/notifyAppReadyAnalytics.spec.ts +243 -0
- package/src/notifyAppReadyAnalytics.test-utils.ts +31 -0
- package/src/notifyAppReadyAnalytics.transport.spec.ts +130 -0
- package/src/notifyAppReadyAnalytics.ts +194 -0
- package/src/releaseCatalogCache.spec.ts +282 -0
- package/src/releaseCatalogCache.ts +341 -0
- package/src/releaseCatalogCacheNativeContract.spec.ts +80 -0
- package/src/sdkVersion.ts +1 -1
- package/src/specs/NativeHotUpdater.ts +51 -5
- package/src/types.ts +0 -140
- package/src/wrap.spec.ts +251 -56
- package/src/wrap.tsx +23 -318
- package/src/wrap.types.ts +78 -0
- package/android/src/main/java/com/hotupdater/StringResourceUtils.kt +0 -45
- package/app.plugin.js +0 -1
- package/ios/HotUpdater/Internal/HotUpdaterCrashHandler.h +0 -7
- package/ios/HotUpdater/Internal/HotUpdaterCrashHandler.mm +0 -4
- package/lib/commonjs/DefaultResolver.js +0 -50
- package/lib/commonjs/DefaultResolver.js.map +0 -1
- package/lib/commonjs/DefaultResolver.spec.js +0 -144
- package/lib/commonjs/DefaultResolver.spec.js.map +0 -1
- package/lib/commonjs/fetchUpdateInfo.js.map +0 -1
- package/lib/module/DefaultResolver.js +0 -46
- package/lib/module/DefaultResolver.js.map +0 -1
- package/lib/module/DefaultResolver.spec.js +0 -144
- package/lib/module/DefaultResolver.spec.js.map +0 -1
- package/lib/module/fetchUpdateInfo.js.map +0 -1
- package/lib/typescript/commonjs/DefaultResolver.d.ts +0 -11
- package/lib/typescript/commonjs/DefaultResolver.d.ts.map +0 -1
- package/lib/typescript/commonjs/fetchUpdateInfo.d.ts +0 -7
- package/lib/typescript/commonjs/fetchUpdateInfo.d.ts.map +0 -1
- package/lib/typescript/module/DefaultResolver.d.ts +0 -11
- package/lib/typescript/module/DefaultResolver.d.ts.map +0 -1
- package/lib/typescript/module/fetchUpdateInfo.d.ts +0 -7
- package/lib/typescript/module/fetchUpdateInfo.d.ts.map +0 -1
- package/plugin/build/transformers.js +0 -314
- package/plugin/build/withHotUpdater.js +0 -228
- package/src/DefaultResolver.spec.ts +0 -193
- package/src/DefaultResolver.ts +0 -63
|
@@ -17,6 +17,9 @@ private func hotUpdaterUpdateSignalLaunchStateSymbol(
|
|
|
17
17
|
@_silgen_name("HotUpdaterPerformRecoveryReload")
|
|
18
18
|
private func hotUpdaterPerformRecoveryReloadSymbol() -> ObjCBool
|
|
19
19
|
|
|
20
|
+
@_silgen_name("HotUpdaterCopyMinBundleId")
|
|
21
|
+
private func hotUpdaterCopyMinBundleIdSymbol() -> UnsafeMutableRawPointer
|
|
22
|
+
|
|
20
23
|
private func hotUpdaterInstallSignalHandlers(_ crashMarkerPath: String) {
|
|
21
24
|
hotUpdaterInstallSignalHandlersSymbol(crashMarkerPath as NSString)
|
|
22
25
|
}
|
|
@@ -29,11 +32,18 @@ private func hotUpdaterPerformRecoveryReload() -> Bool {
|
|
|
29
32
|
return hotUpdaterPerformRecoveryReloadSymbol().boolValue
|
|
30
33
|
}
|
|
31
34
|
|
|
35
|
+
private func hotUpdaterGetMinBundleId() -> String {
|
|
36
|
+
Unmanaged<NSString>
|
|
37
|
+
.fromOpaque(hotUpdaterCopyMinBundleIdSymbol())
|
|
38
|
+
.takeRetainedValue() as String
|
|
39
|
+
}
|
|
40
|
+
|
|
32
41
|
@objcMembers public class HotUpdaterImpl: NSObject {
|
|
33
42
|
private let bundleStorage: BundleStorageService
|
|
34
43
|
private let preferences: PreferencesService
|
|
35
44
|
private let cohortService: CohortService
|
|
36
45
|
private let recoveryManager: HotUpdaterRecoveryManager
|
|
46
|
+
private let releaseCatalogCache: ReleaseCatalogCacheService
|
|
37
47
|
private var currentLaunchSelection: LaunchSelection?
|
|
38
48
|
|
|
39
49
|
private static let DEFAULT_CHANNEL = "production"
|
|
@@ -56,11 +66,17 @@ private func hotUpdaterPerformRecoveryReload() -> Bool {
|
|
|
56
66
|
downloadService: downloadService,
|
|
57
67
|
decompressService: decompressService,
|
|
58
68
|
preferences: preferences,
|
|
59
|
-
isolationKey: isolationKey
|
|
69
|
+
isolationKey: isolationKey,
|
|
70
|
+
builtInBundleIdProvider: { HotUpdaterImpl.minBundleId() }
|
|
60
71
|
)
|
|
61
72
|
let recoveryManager = HotUpdaterRecoveryManager.shared
|
|
62
73
|
|
|
63
|
-
self.init(
|
|
74
|
+
self.init(
|
|
75
|
+
bundleStorage: bundleStorage,
|
|
76
|
+
preferences: preferences,
|
|
77
|
+
recoveryManager: recoveryManager,
|
|
78
|
+
releaseCatalogCache: ReleaseCatalogCacheService()
|
|
79
|
+
)
|
|
64
80
|
}
|
|
65
81
|
|
|
66
82
|
/**
|
|
@@ -68,11 +84,17 @@ private func hotUpdaterPerformRecoveryReload() -> Bool {
|
|
|
68
84
|
* @param bundleStorage Service for bundle storage operations
|
|
69
85
|
* @param preferences Service for preference storage
|
|
70
86
|
*/
|
|
71
|
-
internal init(
|
|
87
|
+
internal init(
|
|
88
|
+
bundleStorage: BundleStorageService,
|
|
89
|
+
preferences: PreferencesService,
|
|
90
|
+
recoveryManager: HotUpdaterRecoveryManager,
|
|
91
|
+
releaseCatalogCache: ReleaseCatalogCacheService = ReleaseCatalogCacheService()
|
|
92
|
+
) {
|
|
72
93
|
self.bundleStorage = bundleStorage
|
|
73
94
|
self.preferences = preferences
|
|
74
95
|
self.cohortService = CohortService()
|
|
75
96
|
self.recoveryManager = recoveryManager
|
|
97
|
+
self.releaseCatalogCache = releaseCatalogCache
|
|
76
98
|
super.init()
|
|
77
99
|
|
|
78
100
|
// Configure preferences with isolation key
|
|
@@ -98,6 +120,10 @@ private func hotUpdaterPerformRecoveryReload() -> Bool {
|
|
|
98
120
|
}
|
|
99
121
|
return Bundle.main.object(forInfoDictionaryKey: "HOT_UPDATER_CHANNEL") as? String ?? Self.DEFAULT_CHANNEL
|
|
100
122
|
}
|
|
123
|
+
|
|
124
|
+
public static func minBundleId() -> String {
|
|
125
|
+
hotUpdaterGetMinBundleId()
|
|
126
|
+
}
|
|
101
127
|
|
|
102
128
|
/**
|
|
103
129
|
* Gets the complete isolation key for preferences storage.
|
|
@@ -136,6 +162,11 @@ private func hotUpdaterPerformRecoveryReload() -> Bool {
|
|
|
136
162
|
* @return The channel name or nil if not set
|
|
137
163
|
*/
|
|
138
164
|
public func getChannel() -> String {
|
|
165
|
+
if let activeSelection = bundleStorage.getActiveUpdateState()["activeSelection"] as? [String: Any],
|
|
166
|
+
let channel = activeSelection["channel"] as? String,
|
|
167
|
+
!channel.isEmpty {
|
|
168
|
+
return channel
|
|
169
|
+
}
|
|
139
170
|
if let override = HotUpdaterConfig.shared.channel, !override.isEmpty {
|
|
140
171
|
return override
|
|
141
172
|
}
|
|
@@ -282,6 +313,16 @@ private func hotUpdaterPerformRecoveryReload() -> Bool {
|
|
|
282
313
|
patch: patch
|
|
283
314
|
)
|
|
284
315
|
}
|
|
316
|
+
let selection = (data["selection"] as? [String: Any]).flatMap(Self.parseSelection)
|
|
317
|
+
if let selection, !bundleStorage.stageReleaseSelection(selection) {
|
|
318
|
+
let error = NSError(
|
|
319
|
+
domain: "HotUpdater",
|
|
320
|
+
code: 0,
|
|
321
|
+
userInfo: [NSLocalizedDescriptionKey: "Release catalog selection is stale"]
|
|
322
|
+
)
|
|
323
|
+
reject("UNKNOWN_ERROR", error.localizedDescription, error)
|
|
324
|
+
return
|
|
325
|
+
}
|
|
285
326
|
|
|
286
327
|
// Extract progress callback if provided
|
|
287
328
|
let progressCallback = data["progressCallback"] as? RCTResponseSenderBlock
|
|
@@ -345,6 +386,122 @@ private func hotUpdaterPerformRecoveryReload() -> Bool {
|
|
|
345
386
|
}
|
|
346
387
|
}
|
|
347
388
|
|
|
389
|
+
private static func parseSelection(_ data: [String: Any]) -> PersistedSelection? {
|
|
390
|
+
guard let kind = data["kind"] as? String,
|
|
391
|
+
let bundleId = data["bundleId"] as? String,
|
|
392
|
+
let channel = data["channel"] as? String else {
|
|
393
|
+
return nil
|
|
394
|
+
}
|
|
395
|
+
return PersistedSelection(
|
|
396
|
+
kind: kind,
|
|
397
|
+
releaseId: data["releaseId"] as? String,
|
|
398
|
+
bundleId: bundleId,
|
|
399
|
+
catalogId: data["catalogId"] as? String,
|
|
400
|
+
scopeKey: data["scopeKey"] as? String,
|
|
401
|
+
generation: (data["generation"] as? NSNumber)?.int64Value,
|
|
402
|
+
catalogHash: data["catalogHash"] as? String,
|
|
403
|
+
channel: channel,
|
|
404
|
+
selectionContextHash: data["selectionContextHash"] as? String
|
|
405
|
+
)
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
public func acceptReleaseCatalog(_ params: NSDictionary?) -> Bool {
|
|
409
|
+
guard let data = params as? [String: Any],
|
|
410
|
+
let catalogId = data["catalogId"] as? String,
|
|
411
|
+
let scopeKey = data["scopeKey"] as? String,
|
|
412
|
+
let generation = data["generation"] as? NSNumber,
|
|
413
|
+
let catalogHash = data["catalogHash"] as? String,
|
|
414
|
+
let channel = data["channel"] as? String,
|
|
415
|
+
let selectionContextHash = data["selectionContextHash"] as? String else {
|
|
416
|
+
return false
|
|
417
|
+
}
|
|
418
|
+
return bundleStorage.acceptReleaseCatalog(
|
|
419
|
+
catalogId: catalogId,
|
|
420
|
+
scopeKey: scopeKey,
|
|
421
|
+
generation: generation.int64Value,
|
|
422
|
+
catalogHash: catalogHash,
|
|
423
|
+
channel: channel,
|
|
424
|
+
selectionContextHash: selectionContextHash
|
|
425
|
+
)
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
public func getActiveUpdateState() -> [String: Any] {
|
|
429
|
+
bundleStorage.getActiveUpdateState()
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
public func getReleaseCatalogCache(
|
|
433
|
+
_ partition: String,
|
|
434
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
435
|
+
rejecter _: @escaping RCTPromiseRejectBlock
|
|
436
|
+
) {
|
|
437
|
+
DispatchQueue.global(qos: .utility).async {
|
|
438
|
+
guard let value = self.releaseCatalogCache.get(partition: partition) else {
|
|
439
|
+
resolve(NSNull())
|
|
440
|
+
return
|
|
441
|
+
}
|
|
442
|
+
resolve(value)
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
public func setReleaseCatalogCache(
|
|
447
|
+
_ partition: String,
|
|
448
|
+
payload: String,
|
|
449
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
450
|
+
rejecter _: @escaping RCTPromiseRejectBlock
|
|
451
|
+
) {
|
|
452
|
+
DispatchQueue.global(qos: .utility).async {
|
|
453
|
+
resolve(self.releaseCatalogCache.set(partition: partition, value: payload))
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
public func removeReleaseCatalogCache(
|
|
458
|
+
_ partition: String,
|
|
459
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
460
|
+
rejecter _: @escaping RCTPromiseRejectBlock
|
|
461
|
+
) {
|
|
462
|
+
DispatchQueue.global(qos: .utility).async {
|
|
463
|
+
resolve(self.releaseCatalogCache.remove(partition: partition))
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
public func isReleaseSelectionCurrent(_ params: NSDictionary?) -> Bool {
|
|
468
|
+
guard let data = params as? [String: Any],
|
|
469
|
+
let catalogId = data["catalogId"] as? String,
|
|
470
|
+
let scopeKey = data["scopeKey"] as? String,
|
|
471
|
+
let generation = data["generation"] as? NSNumber,
|
|
472
|
+
let catalogHash = data["catalogHash"] as? String,
|
|
473
|
+
let channel = data["channel"] as? String,
|
|
474
|
+
let selectionContextHash = data["selectionContextHash"] as? String else {
|
|
475
|
+
return false
|
|
476
|
+
}
|
|
477
|
+
return bundleStorage.isReleaseSelectionCurrent(
|
|
478
|
+
catalogId: catalogId,
|
|
479
|
+
scopeKey: scopeKey,
|
|
480
|
+
generation: generation.int64Value,
|
|
481
|
+
catalogHash: catalogHash,
|
|
482
|
+
channel: channel,
|
|
483
|
+
selectionContextHash: selectionContextHash
|
|
484
|
+
)
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
public func commitReleaseSelection(
|
|
488
|
+
_ params: NSDictionary?,
|
|
489
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
490
|
+
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
491
|
+
) {
|
|
492
|
+
guard let data = params?["selection"] as? [String: Any],
|
|
493
|
+
let selection = Self.parseSelection(data) else {
|
|
494
|
+
let error = NSError(
|
|
495
|
+
domain: "HotUpdater",
|
|
496
|
+
code: 0,
|
|
497
|
+
userInfo: [NSLocalizedDescriptionKey: "Invalid Release selection"]
|
|
498
|
+
)
|
|
499
|
+
reject("INVALID_SELECTION", error.localizedDescription, error)
|
|
500
|
+
return
|
|
501
|
+
}
|
|
502
|
+
resolve(bundleStorage.commitReleaseSelection(selection))
|
|
503
|
+
}
|
|
504
|
+
|
|
348
505
|
/**
|
|
349
506
|
* Normalizes native errors to a small, predictable set of JS-facing error codes.
|
|
350
507
|
* Rare or platform-specific codes are collapsed to UNKNOWN_ERROR to reduce surface area.
|
|
@@ -387,10 +544,6 @@ private func hotUpdaterPerformRecoveryReload() -> Bool {
|
|
|
387
544
|
|
|
388
545
|
// MARK: - Rollback Support
|
|
389
546
|
|
|
390
|
-
/**
|
|
391
|
-
* Returns the native launch report for the current process.
|
|
392
|
-
* This is read-only; startup success and rollback are finalized before JS reads it.
|
|
393
|
-
*/
|
|
394
547
|
public func notifyAppReady() -> [String: Any] {
|
|
395
548
|
return bundleStorage.notifyAppReady()
|
|
396
549
|
}
|
|
@@ -411,6 +564,22 @@ private func hotUpdaterPerformRecoveryReload() -> Bool {
|
|
|
411
564
|
return bundleStorage.clearCrashHistory()
|
|
412
565
|
}
|
|
413
566
|
|
|
567
|
+
public func getInstallId() -> String {
|
|
568
|
+
return bundleStorage.getInstallId()
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
public func getUserId() -> String? {
|
|
572
|
+
return bundleStorage.getUserId()
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
public func getUsername() -> String? {
|
|
576
|
+
return bundleStorage.getUsername()
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
public func setUser(_ userId: String?, username: String?) {
|
|
580
|
+
bundleStorage.setUser(userId: userId, username: username)
|
|
581
|
+
}
|
|
582
|
+
|
|
414
583
|
/**
|
|
415
584
|
* Gets the base URL for the current active bundle directory.
|
|
416
585
|
* Returns the file:// URL to the bundle directory with trailing slash.
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import CryptoKit
|
|
2
|
+
import Foundation
|
|
3
|
+
|
|
4
|
+
final class ReleaseCatalogCacheService {
|
|
5
|
+
private static let maxCompiledCatalogBytes = 256 * 1024
|
|
6
|
+
private static let maxWireEnvelopeBytes = 4 * 1024
|
|
7
|
+
private static let maxETagBytes = 1024
|
|
8
|
+
private static let cacheFormatBytes = 3
|
|
9
|
+
static let defaultMaxEntries = 8
|
|
10
|
+
static let defaultMaxEntryBytes =
|
|
11
|
+
maxCompiledCatalogBytes + maxWireEnvelopeBytes + maxETagBytes + cacheFormatBytes
|
|
12
|
+
static let defaultMaxTotalBytes = defaultMaxEntries * (defaultMaxEntryBytes + 65)
|
|
13
|
+
|
|
14
|
+
private let fileManager: FileManager
|
|
15
|
+
private let rootDirectory: URL
|
|
16
|
+
private let maxEntries: Int
|
|
17
|
+
private let maxEntryBytes: Int
|
|
18
|
+
private let maxTotalBytes: Int
|
|
19
|
+
private let atomicWriter: (Data, URL) throws -> Void
|
|
20
|
+
private let lock = NSLock()
|
|
21
|
+
|
|
22
|
+
init(
|
|
23
|
+
rootDirectory: URL = ReleaseCatalogCacheService.defaultRootDirectory(),
|
|
24
|
+
fileManager: FileManager = .default,
|
|
25
|
+
maxEntries: Int = defaultMaxEntries,
|
|
26
|
+
maxEntryBytes: Int = defaultMaxEntryBytes,
|
|
27
|
+
maxTotalBytes: Int = defaultMaxTotalBytes,
|
|
28
|
+
atomicWriter: @escaping (Data, URL) throws -> Void = ReleaseCatalogCacheService.writeAtomically
|
|
29
|
+
) {
|
|
30
|
+
self.rootDirectory = rootDirectory
|
|
31
|
+
self.fileManager = fileManager
|
|
32
|
+
self.maxEntries = maxEntries
|
|
33
|
+
self.maxEntryBytes = maxEntryBytes
|
|
34
|
+
self.maxTotalBytes = maxTotalBytes
|
|
35
|
+
self.atomicWriter = atomicWriter
|
|
36
|
+
recoverInterruptedWrites()
|
|
37
|
+
trim()
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
func get(partition: String) -> String? {
|
|
41
|
+
lock.lock()
|
|
42
|
+
defer { lock.unlock() }
|
|
43
|
+
|
|
44
|
+
let file = entryURL(partition: partition)
|
|
45
|
+
guard let attributes = try? fileManager.attributesOfItem(atPath: file.path),
|
|
46
|
+
let size = attributes[.size] as? NSNumber,
|
|
47
|
+
size.intValue <= maxEntryBytes + 65,
|
|
48
|
+
let stored = try? Data(contentsOf: file),
|
|
49
|
+
let separator = stored.firstIndex(of: 0x0a),
|
|
50
|
+
separator == 64 else {
|
|
51
|
+
try? fileManager.removeItem(at: file)
|
|
52
|
+
return nil
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
let expectedDigest = String(data: stored[..<separator], encoding: .ascii)
|
|
56
|
+
let payload = stored[stored.index(after: separator)...]
|
|
57
|
+
guard payload.count <= maxEntryBytes,
|
|
58
|
+
expectedDigest == sha256(Data(payload)),
|
|
59
|
+
let value = String(data: payload, encoding: .utf8) else {
|
|
60
|
+
try? fileManager.removeItem(at: file)
|
|
61
|
+
return nil
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
try? fileManager.setAttributes(
|
|
65
|
+
[.modificationDate: Date()],
|
|
66
|
+
ofItemAtPath: file.path
|
|
67
|
+
)
|
|
68
|
+
return value
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
@discardableResult
|
|
72
|
+
func set(partition: String, value: String) -> Bool {
|
|
73
|
+
guard let payload = value.data(using: .utf8), payload.count <= maxEntryBytes else {
|
|
74
|
+
return false
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
lock.lock()
|
|
78
|
+
defer { lock.unlock() }
|
|
79
|
+
|
|
80
|
+
do {
|
|
81
|
+
try fileManager.createDirectory(
|
|
82
|
+
at: rootDirectory,
|
|
83
|
+
withIntermediateDirectories: true
|
|
84
|
+
)
|
|
85
|
+
var cacheDirectory = rootDirectory
|
|
86
|
+
var resourceValues = URLResourceValues()
|
|
87
|
+
resourceValues.isExcludedFromBackup = true
|
|
88
|
+
try? cacheDirectory.setResourceValues(resourceValues)
|
|
89
|
+
var stored = Data(sha256(payload).utf8)
|
|
90
|
+
stored.append(0x0a)
|
|
91
|
+
stored.append(payload)
|
|
92
|
+
let destination = entryURL(partition: partition)
|
|
93
|
+
try atomicWriter(stored, destination)
|
|
94
|
+
try? fileManager.setAttributes(
|
|
95
|
+
[.modificationDate: Date()],
|
|
96
|
+
ofItemAtPath: destination.path
|
|
97
|
+
)
|
|
98
|
+
trim()
|
|
99
|
+
return true
|
|
100
|
+
} catch {
|
|
101
|
+
return false
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
@discardableResult
|
|
106
|
+
func remove(partition: String) -> Bool {
|
|
107
|
+
lock.lock()
|
|
108
|
+
defer { lock.unlock() }
|
|
109
|
+
|
|
110
|
+
let file = entryURL(partition: partition)
|
|
111
|
+
guard fileManager.fileExists(atPath: file.path) else { return true }
|
|
112
|
+
do {
|
|
113
|
+
try fileManager.removeItem(at: file)
|
|
114
|
+
return true
|
|
115
|
+
} catch {
|
|
116
|
+
return false
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
private func entryURL(partition: String) -> URL {
|
|
121
|
+
rootDirectory
|
|
122
|
+
.appendingPathComponent(sha256(Data(partition.utf8)))
|
|
123
|
+
.appendingPathExtension("catalog")
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
private func recoverInterruptedWrites() {
|
|
127
|
+
guard let entries = try? fileManager.contentsOfDirectory(
|
|
128
|
+
at: rootDirectory,
|
|
129
|
+
includingPropertiesForKeys: nil,
|
|
130
|
+
options: []
|
|
131
|
+
) else {
|
|
132
|
+
return
|
|
133
|
+
}
|
|
134
|
+
for entry in entries
|
|
135
|
+
where entry.lastPathComponent.hasPrefix(".catalog-") && entry.pathExtension == "tmp" {
|
|
136
|
+
try? fileManager.removeItem(at: entry)
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
private func trim() {
|
|
141
|
+
let keys: Set<URLResourceKey> = [
|
|
142
|
+
.contentModificationDateKey,
|
|
143
|
+
.fileSizeKey,
|
|
144
|
+
.isRegularFileKey,
|
|
145
|
+
]
|
|
146
|
+
let entries = (try? fileManager.contentsOfDirectory(
|
|
147
|
+
at: rootDirectory,
|
|
148
|
+
includingPropertiesForKeys: Array(keys),
|
|
149
|
+
options: [.skipsHiddenFiles]
|
|
150
|
+
))?
|
|
151
|
+
.filter { url in
|
|
152
|
+
guard url.pathExtension == "catalog",
|
|
153
|
+
let values = try? url.resourceValues(forKeys: keys) else {
|
|
154
|
+
return false
|
|
155
|
+
}
|
|
156
|
+
return values.isRegularFile == true
|
|
157
|
+
}
|
|
158
|
+
.sorted { first, second in
|
|
159
|
+
let firstDate = (try? first.resourceValues(forKeys: keys))?.contentModificationDate ?? .distantPast
|
|
160
|
+
let secondDate = (try? second.resourceValues(forKeys: keys))?.contentModificationDate ?? .distantPast
|
|
161
|
+
return firstDate > secondDate
|
|
162
|
+
} ?? []
|
|
163
|
+
|
|
164
|
+
var retainedBytes = 0
|
|
165
|
+
for (index, entry) in entries.enumerated() {
|
|
166
|
+
let size = (try? entry.resourceValues(forKeys: keys))?.fileSize ?? 0
|
|
167
|
+
retainedBytes += size
|
|
168
|
+
if index >= maxEntries || retainedBytes > maxTotalBytes {
|
|
169
|
+
try? fileManager.removeItem(at: entry)
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
private func sha256(_ value: Data) -> String {
|
|
175
|
+
SHA256.hash(data: value).map { String(format: "%02x", $0) }.joined()
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
private static func writeAtomically(_ data: Data, to destination: URL) throws {
|
|
179
|
+
let temporary = destination
|
|
180
|
+
.deletingLastPathComponent()
|
|
181
|
+
.appendingPathComponent(".catalog-\(UUID().uuidString).tmp")
|
|
182
|
+
do {
|
|
183
|
+
try data.write(to: temporary, options: .withoutOverwriting)
|
|
184
|
+
let handle = try FileHandle(forWritingTo: temporary)
|
|
185
|
+
try handle.synchronize()
|
|
186
|
+
try handle.close()
|
|
187
|
+
|
|
188
|
+
if FileManager.default.fileExists(atPath: destination.path) {
|
|
189
|
+
_ = try FileManager.default.replaceItemAt(
|
|
190
|
+
destination,
|
|
191
|
+
withItemAt: temporary,
|
|
192
|
+
backupItemName: nil,
|
|
193
|
+
options: []
|
|
194
|
+
)
|
|
195
|
+
} else {
|
|
196
|
+
try FileManager.default.moveItem(at: temporary, to: destination)
|
|
197
|
+
}
|
|
198
|
+
} catch {
|
|
199
|
+
try? FileManager.default.removeItem(at: temporary)
|
|
200
|
+
throw error
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
private static func defaultRootDirectory() -> URL {
|
|
205
|
+
let base = FileManager.default.urls(
|
|
206
|
+
for: .applicationSupportDirectory,
|
|
207
|
+
in: .userDomainMask
|
|
208
|
+
).first ?? FileManager.default.temporaryDirectory
|
|
209
|
+
return base
|
|
210
|
+
.appendingPathComponent("HotUpdater", isDirectory: true)
|
|
211
|
+
.appendingPathComponent("ReleaseCatalogCache", isDirectory: true)
|
|
212
|
+
}
|
|
213
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.writeNativeReleaseCatalogCache = exports.removeNativeReleaseCatalogCache = exports.readNativeReleaseCatalogCache = void 0;
|
|
7
|
+
var _NativeHotUpdater = _interopRequireDefault(require("./specs/NativeHotUpdater.js"));
|
|
8
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
9
|
+
const getModule = () => _NativeHotUpdater.default;
|
|
10
|
+
const requireMethod = (method, name) => {
|
|
11
|
+
if (typeof method !== "function") {
|
|
12
|
+
throw new Error(`[HotUpdater] Native module is missing '${name}()'. Rebuild the native app before using Release catalogs.`);
|
|
13
|
+
}
|
|
14
|
+
return method;
|
|
15
|
+
};
|
|
16
|
+
const readNativeReleaseCatalogCache = async partition => {
|
|
17
|
+
const method = requireMethod(getModule().getReleaseCatalogCache, "getReleaseCatalogCache");
|
|
18
|
+
try {
|
|
19
|
+
const value = await method.call(_NativeHotUpdater.default, partition);
|
|
20
|
+
return typeof value === "string" ? value : null;
|
|
21
|
+
} catch {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
exports.readNativeReleaseCatalogCache = readNativeReleaseCatalogCache;
|
|
26
|
+
const writeNativeReleaseCatalogCache = async (partition, payload) => {
|
|
27
|
+
const method = requireMethod(getModule().setReleaseCatalogCache, "setReleaseCatalogCache");
|
|
28
|
+
try {
|
|
29
|
+
return await method.call(_NativeHotUpdater.default, partition, payload);
|
|
30
|
+
} catch {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
exports.writeNativeReleaseCatalogCache = writeNativeReleaseCatalogCache;
|
|
35
|
+
const removeNativeReleaseCatalogCache = async partition => {
|
|
36
|
+
const method = requireMethod(getModule().removeReleaseCatalogCache, "removeReleaseCatalogCache");
|
|
37
|
+
try {
|
|
38
|
+
await method.call(_NativeHotUpdater.default, partition);
|
|
39
|
+
} catch {
|
|
40
|
+
// Cache maintenance must not prevent a network update check.
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
exports.removeNativeReleaseCatalogCache = removeNativeReleaseCatalogCache;
|
|
44
|
+
//# sourceMappingURL=catalogCacheNative.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_NativeHotUpdater","_interopRequireDefault","require","e","__esModule","default","getModule","HotUpdaterNative","requireMethod","method","name","Error","readNativeReleaseCatalogCache","partition","getReleaseCatalogCache","value","call","exports","writeNativeReleaseCatalogCache","payload","setReleaseCatalogCache","removeNativeReleaseCatalogCache","removeReleaseCatalogCache"],"sourceRoot":"../../src","sources":["catalogCacheNative.ts"],"mappings":";;;;;;AAAA,IAAAA,iBAAA,GAAAC,sBAAA,CAAAC,OAAA;AAAwD,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAaxD,MAAMG,SAAS,GAAGA,CAAA,KAChBC,yBAAsE;AAExE,MAAMC,aAAa,GAAGA,CACpBC,MAAqB,EACrBC,IAAkC,KAC5B;EACN,IAAI,OAAOD,MAAM,KAAK,UAAU,EAAE;IAChC,MAAM,IAAIE,KAAK,CACb,0CAA0CD,IAAI,4DAChD,CAAC;EACH;EACA,OAAOD,MAAM;AACf,CAAC;AAEM,MAAMG,6BAA6B,GAAG,MAC3CC,SAAiB,IACU;EAC3B,MAAMJ,MAAM,GAAGD,aAAa,CAC1BF,SAAS,CAAC,CAAC,CAACQ,sBAAsB,EAClC,wBACF,CAAC;EAED,IAAI;IACF,MAAMC,KAAK,GAAG,MAAMN,MAAM,CAACO,IAAI,CAACT,yBAAgB,EAAEM,SAAS,CAAC;IAC5D,OAAO,OAAOE,KAAK,KAAK,QAAQ,GAAGA,KAAK,GAAG,IAAI;EACjD,CAAC,CAAC,MAAM;IACN,OAAO,IAAI;EACb;AACF,CAAC;AAACE,OAAA,CAAAL,6BAAA,GAAAA,6BAAA;AAEK,MAAMM,8BAA8B,GAAG,MAAAA,CAC5CL,SAAiB,EACjBM,OAAe,KACM;EACrB,MAAMV,MAAM,GAAGD,aAAa,CAC1BF,SAAS,CAAC,CAAC,CAACc,sBAAsB,EAClC,wBACF,CAAC;EAED,IAAI;IACF,OAAO,MAAMX,MAAM,CAACO,IAAI,CAACT,yBAAgB,EAAEM,SAAS,EAAEM,OAAO,CAAC;EAChE,CAAC,CAAC,MAAM;IACN,OAAO,KAAK;EACd;AACF,CAAC;AAACF,OAAA,CAAAC,8BAAA,GAAAA,8BAAA;AAEK,MAAMG,+BAA+B,GAAG,MAC7CR,SAAiB,IACC;EAClB,MAAMJ,MAAM,GAAGD,aAAa,CAC1BF,SAAS,CAAC,CAAC,CAACgB,yBAAyB,EACrC,2BACF,CAAC;EAED,IAAI;IACF,MAAMb,MAAM,CAACO,IAAI,CAACT,yBAAgB,EAAEM,SAAS,CAAC;EAChD,CAAC,CAAC,MAAM;IACN;EAAA;AAEJ,CAAC;AAACI,OAAA,CAAAI,+BAAA,GAAAA,+BAAA","ignoreList":[]}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _vitest = require("vitest");
|
|
4
|
+
var _catalogCacheNative = require("./catalogCacheNative.js");
|
|
5
|
+
const nativeModule = _vitest.vi.hoisted(() => ({}));
|
|
6
|
+
_vitest.vi.mock("./specs/NativeHotUpdater", () => ({
|
|
7
|
+
default: nativeModule
|
|
8
|
+
}));
|
|
9
|
+
(0, _vitest.describe)("Release Catalog native cache", () => {
|
|
10
|
+
(0, _vitest.beforeEach)(() => {
|
|
11
|
+
for (const key of Object.keys(nativeModule)) delete nativeModule[key];
|
|
12
|
+
});
|
|
13
|
+
(0, _vitest.it)("fails fast when the v1 native cache API is missing", async () => {
|
|
14
|
+
await (0, _vitest.expect)((0, _catalogCacheNative.readNativeReleaseCatalogCache)("partition")).rejects.toThrow("Native module is missing 'getReleaseCatalogCache()'. Rebuild the native app before using Release catalogs.");
|
|
15
|
+
await (0, _vitest.expect)((0, _catalogCacheNative.writeNativeReleaseCatalogCache)("partition", "payload")).rejects.toThrow("Native module is missing 'setReleaseCatalogCache()'. Rebuild the native app before using Release catalogs.");
|
|
16
|
+
await (0, _vitest.expect)((0, _catalogCacheNative.removeNativeReleaseCatalogCache)("partition")).rejects.toThrow("Native module is missing 'removeReleaseCatalogCache()'. Rebuild the native app before using Release catalogs.");
|
|
17
|
+
});
|
|
18
|
+
(0, _vitest.it)("normalizes an undefined iOS TurboModule cache miss to null", async () => {
|
|
19
|
+
nativeModule.getReleaseCatalogCache = _vitest.vi.fn().mockResolvedValue(undefined);
|
|
20
|
+
await (0, _vitest.expect)((0, _catalogCacheNative.readNativeReleaseCatalogCache)("partition")).resolves.toBeNull();
|
|
21
|
+
});
|
|
22
|
+
(0, _vitest.it)("treats native cache I/O failures as misses without hiding network work", async () => {
|
|
23
|
+
nativeModule.getReleaseCatalogCache = _vitest.vi.fn().mockRejectedValue(new Error("read"));
|
|
24
|
+
nativeModule.setReleaseCatalogCache = _vitest.vi.fn().mockRejectedValue(new Error("write"));
|
|
25
|
+
nativeModule.removeReleaseCatalogCache = _vitest.vi.fn().mockRejectedValue(new Error("remove"));
|
|
26
|
+
await (0, _vitest.expect)((0, _catalogCacheNative.readNativeReleaseCatalogCache)("partition")).resolves.toBeNull();
|
|
27
|
+
await (0, _vitest.expect)((0, _catalogCacheNative.writeNativeReleaseCatalogCache)("partition", "payload")).resolves.toBe(false);
|
|
28
|
+
await (0, _vitest.expect)((0, _catalogCacheNative.removeNativeReleaseCatalogCache)("partition")).resolves.toBeUndefined();
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
//# sourceMappingURL=catalogCacheNative.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_vitest","require","_catalogCacheNative","nativeModule","vi","hoisted","mock","default","describe","beforeEach","key","Object","keys","it","expect","readNativeReleaseCatalogCache","rejects","toThrow","writeNativeReleaseCatalogCache","removeNativeReleaseCatalogCache","getReleaseCatalogCache","fn","mockResolvedValue","undefined","resolves","toBeNull","mockRejectedValue","Error","setReleaseCatalogCache","removeReleaseCatalogCache","toBe","toBeUndefined"],"sourceRoot":"../../src","sources":["catalogCacheNative.spec.ts"],"mappings":";;AAAA,IAAAA,OAAA,GAAAC,OAAA;AAQA,IAAAC,mBAAA,GAAAD,OAAA;AANA,MAAME,YAAY,GAAGC,UAAE,CAACC,OAAO,CAC7B,OAAO,CAAC,CAAC,CACX,CAAC;AAEDD,UAAE,CAACE,IAAI,CAAC,0BAA0B,EAAE,OAAO;EAAEC,OAAO,EAAEJ;AAAa,CAAC,CAAC,CAAC;AAQtE,IAAAK,gBAAQ,EAAC,8BAA8B,EAAE,MAAM;EAC7C,IAAAC,kBAAU,EAAC,MAAM;IACf,KAAK,MAAMC,GAAG,IAAIC,MAAM,CAACC,IAAI,CAACT,YAAY,CAAC,EAAE,OAAOA,YAAY,CAACO,GAAG,CAAC;EACvE,CAAC,CAAC;EAEF,IAAAG,UAAE,EAAC,oDAAoD,EAAE,YAAY;IACnE,MAAM,IAAAC,cAAM,EAAC,IAAAC,iDAA6B,EAAC,WAAW,CAAC,CAAC,CAACC,OAAO,CAACC,OAAO,CACtE,4GACF,CAAC;IACD,MAAM,IAAAH,cAAM,EACV,IAAAI,kDAA8B,EAAC,WAAW,EAAE,SAAS,CACvD,CAAC,CAACF,OAAO,CAACC,OAAO,CACf,4GACF,CAAC;IACD,MAAM,IAAAH,cAAM,EAAC,IAAAK,mDAA+B,EAAC,WAAW,CAAC,CAAC,CAACH,OAAO,CAACC,OAAO,CACxE,+GACF,CAAC;EACH,CAAC,CAAC;EAEF,IAAAJ,UAAE,EAAC,4DAA4D,EAAE,YAAY;IAC3EV,YAAY,CAACiB,sBAAsB,GAAGhB,UAAE,CAACiB,EAAE,CAAC,CAAC,CAACC,iBAAiB,CAACC,SAAS,CAAC;IAE1E,MAAM,IAAAT,cAAM,EACV,IAAAC,iDAA6B,EAAC,WAAW,CAC3C,CAAC,CAACS,QAAQ,CAACC,QAAQ,CAAC,CAAC;EACvB,CAAC,CAAC;EAEF,IAAAZ,UAAE,EAAC,wEAAwE,EAAE,YAAY;IACvFV,YAAY,CAACiB,sBAAsB,GAAGhB,UAAE,CACrCiB,EAAE,CAAC,CAAC,CACJK,iBAAiB,CAAC,IAAIC,KAAK,CAAC,MAAM,CAAC,CAAC;IACvCxB,YAAY,CAACyB,sBAAsB,GAAGxB,UAAE,CACrCiB,EAAE,CAAC,CAAC,CACJK,iBAAiB,CAAC,IAAIC,KAAK,CAAC,OAAO,CAAC,CAAC;IACxCxB,YAAY,CAAC0B,yBAAyB,GAAGzB,UAAE,CACxCiB,EAAE,CAAC,CAAC,CACJK,iBAAiB,CAAC,IAAIC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAEzC,MAAM,IAAAb,cAAM,EACV,IAAAC,iDAA6B,EAAC,WAAW,CAC3C,CAAC,CAACS,QAAQ,CAACC,QAAQ,CAAC,CAAC;IACrB,MAAM,IAAAX,cAAM,EACV,IAAAI,kDAA8B,EAAC,WAAW,EAAE,SAAS,CACvD,CAAC,CAACM,QAAQ,CAACM,IAAI,CAAC,KAAK,CAAC;IACtB,MAAM,IAAAhB,cAAM,EACV,IAAAK,mDAA+B,EAAC,WAAW,CAC7C,CAAC,CAACK,QAAQ,CAACO,aAAa,CAAC,CAAC;EAC5B,CAAC,CAAC;AACJ,CAAC,CAAC","ignoreList":[]}
|