@hot-updater/react-native 1.0.0-rc.2 → 1.0.0-rc.22

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.
Files changed (291) hide show
  1. package/android/proguard-rules.pro +17 -2
  2. package/android/src/main/java/com/hotupdater/BuiltInAssetResolver.kt +286 -0
  3. package/android/src/main/java/com/hotupdater/BundleFileStorageService.kt +954 -837
  4. package/android/src/main/java/com/hotupdater/BundleMetadata.kt +15 -11
  5. package/android/src/main/java/com/hotupdater/FileManagerService.kt +45 -0
  6. package/android/src/main/java/com/hotupdater/HotUpdaterException.kt +287 -22
  7. package/android/src/main/java/com/hotupdater/HotUpdaterImpl.kt +43 -31
  8. package/android/src/main/java/com/hotupdater/HotUpdaterRecoveryManager.kt +37 -54
  9. package/android/src/main/java/com/hotupdater/HotUpdaterRecoveryState.kt +64 -0
  10. package/android/src/main/java/com/hotupdater/InstallIdentityService.kt +37 -0
  11. package/android/src/main/java/com/hotupdater/KeyValueStorageService.kt +86 -0
  12. package/android/src/main/java/com/hotupdater/NetworkState.kt +31 -0
  13. package/android/src/main/java/com/hotupdater/NoBackupStorage.kt +17 -0
  14. package/android/src/main/java/com/hotupdater/OkHttpDownloadService.kt +127 -50
  15. package/android/src/main/java/com/hotupdater/PreviousProcessExit.kt +89 -0
  16. package/android/src/main/java/com/hotupdater/ReactNativeValueConverters.kt +34 -0
  17. package/android/src/main/java/com/hotupdater/TarArchiveInputStream.kt +214 -375
  18. package/android/src/main/java/com/hotupdater/TarBrArchiveExtractor.kt +119 -0
  19. package/android/src/newarch/HotUpdater.kt +7 -9
  20. package/android/src/newarch/HotUpdaterModule.kt +109 -84
  21. package/android/src/oldarch/HotUpdater.kt +7 -9
  22. package/android/src/oldarch/HotUpdaterModule.kt +98 -74
  23. package/android/src/oldarch/HotUpdaterSpec.kt +4 -6
  24. package/ios/HotUpdater/Internal/BrotliFileDecompressor.swift +167 -0
  25. package/ios/HotUpdater/Internal/BuiltInAssetResolver.swift +196 -0
  26. package/ios/HotUpdater/Internal/BundleFileStorageService.swift +950 -1112
  27. package/ios/HotUpdater/Internal/BundleMetadata.swift +8 -53
  28. package/ios/HotUpdater/Internal/FileManagerService.swift +48 -0
  29. package/ios/HotUpdater/Internal/FileUtilities.swift +64 -0
  30. package/ios/HotUpdater/Internal/HotUpdater-Bridging-Header.h +0 -1
  31. package/ios/HotUpdater/Internal/HotUpdater.mm +13 -45
  32. package/ios/HotUpdater/Internal/HotUpdaterImpl.swift +190 -73
  33. package/ios/HotUpdater/Internal/KeyValueStorageService.swift +71 -0
  34. package/ios/HotUpdater/Internal/NotificationExtension.swift +0 -2
  35. package/ios/HotUpdater/Internal/TarArchiveExtractor.swift +182 -311
  36. package/ios/HotUpdater/Internal/URLSessionDownloadService.swift +119 -71
  37. package/ios/HotUpdater/Internal/UpdateFailure.swift +390 -0
  38. package/ios/HotUpdater/Recovery/HotUpdaterRecovery.h +16 -0
  39. package/ios/HotUpdater/Recovery/HotUpdaterRecovery.mm +83 -0
  40. package/ios/HotUpdater/Recovery/HotUpdaterRecoveryHooks.mm +49 -0
  41. package/lib/commonjs/appReady.js +111 -0
  42. package/lib/commonjs/appReady.js.map +1 -0
  43. package/lib/commonjs/checkForUpdate.js +125 -70
  44. package/lib/commonjs/checkForUpdate.js.map +1 -1
  45. package/lib/commonjs/clientPlugin.js +13 -0
  46. package/lib/commonjs/clientPlugin.js.map +1 -0
  47. package/lib/commonjs/error.js +4 -13
  48. package/lib/commonjs/error.js.map +1 -1
  49. package/lib/commonjs/fetchJSON.js +5 -2
  50. package/lib/commonjs/fetchJSON.js.map +1 -1
  51. package/lib/commonjs/httpClient.js +55 -92
  52. package/lib/commonjs/httpClient.js.map +1 -1
  53. package/lib/commonjs/index.js +68 -20
  54. package/lib/commonjs/index.js.map +1 -1
  55. package/lib/commonjs/native.js +82 -62
  56. package/lib/commonjs/native.js.map +1 -1
  57. package/lib/commonjs/pluginHost.js +44 -0
  58. package/lib/commonjs/pluginHost.js.map +1 -0
  59. package/lib/commonjs/releaseCatalogCache.js +20 -61
  60. package/lib/commonjs/releaseCatalogCache.js.map +1 -1
  61. package/lib/commonjs/sdkVersion.js +1 -1
  62. package/lib/commonjs/sdkVersion.js.map +1 -1
  63. package/lib/commonjs/specs/NativeHotUpdater.js.map +1 -1
  64. package/lib/commonjs/store.js +3 -10
  65. package/lib/commonjs/store.js.map +1 -1
  66. package/lib/commonjs/updateError.js +132 -0
  67. package/lib/commonjs/updateError.js.map +1 -0
  68. package/lib/commonjs/wrap.js +44 -27
  69. package/lib/commonjs/wrap.js.map +1 -1
  70. package/lib/module/appReady.js +103 -0
  71. package/lib/module/appReady.js.map +1 -0
  72. package/lib/module/checkForUpdate.js +118 -65
  73. package/lib/module/checkForUpdate.js.map +1 -1
  74. package/lib/module/clientPlugin.js +4 -0
  75. package/lib/module/clientPlugin.js.map +1 -0
  76. package/lib/module/error.js +4 -13
  77. package/lib/module/error.js.map +1 -1
  78. package/lib/module/fetchJSON.js +3 -1
  79. package/lib/module/fetchJSON.js.map +1 -1
  80. package/lib/module/httpClient.js +53 -90
  81. package/lib/module/httpClient.js.map +1 -1
  82. package/lib/module/index.js +55 -22
  83. package/lib/module/index.js.map +1 -1
  84. package/lib/module/native.js +74 -54
  85. package/lib/module/native.js.map +1 -1
  86. package/lib/module/pluginHost.js +35 -0
  87. package/lib/module/pluginHost.js.map +1 -0
  88. package/lib/module/releaseCatalogCache.js +16 -56
  89. package/lib/module/releaseCatalogCache.js.map +1 -1
  90. package/lib/module/sdkVersion.js +1 -1
  91. package/lib/module/sdkVersion.js.map +1 -1
  92. package/lib/module/specs/NativeHotUpdater.js.map +1 -1
  93. package/lib/module/store.js +3 -10
  94. package/lib/module/store.js.map +1 -1
  95. package/lib/module/updateError.js +126 -0
  96. package/lib/module/updateError.js.map +1 -0
  97. package/lib/module/wrap.js +45 -28
  98. package/lib/module/wrap.js.map +1 -1
  99. package/lib/typescript/commonjs/appReady.d.ts +23 -0
  100. package/lib/typescript/commonjs/appReady.d.ts.map +1 -0
  101. package/lib/typescript/commonjs/checkForUpdate.d.ts +16 -4
  102. package/lib/typescript/commonjs/checkForUpdate.d.ts.map +1 -1
  103. package/lib/typescript/commonjs/clientPlugin.d.ts +2 -0
  104. package/lib/typescript/commonjs/clientPlugin.d.ts.map +1 -0
  105. package/lib/typescript/commonjs/error.d.ts +4 -13
  106. package/lib/typescript/commonjs/error.d.ts.map +1 -1
  107. package/lib/typescript/commonjs/fetchJSON.d.ts +3 -0
  108. package/lib/typescript/commonjs/fetchJSON.d.ts.map +1 -1
  109. package/lib/typescript/commonjs/httpClient.d.ts +3 -32
  110. package/lib/typescript/commonjs/httpClient.d.ts.map +1 -1
  111. package/lib/typescript/commonjs/index.d.ts +7 -12
  112. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  113. package/lib/typescript/commonjs/native.d.ts +33 -23
  114. package/lib/typescript/commonjs/native.d.ts.map +1 -1
  115. package/lib/typescript/commonjs/pluginHost.d.ts +4 -0
  116. package/lib/typescript/commonjs/pluginHost.d.ts.map +1 -0
  117. package/lib/typescript/commonjs/releaseCatalogCache.d.ts +6 -14
  118. package/lib/typescript/commonjs/releaseCatalogCache.d.ts.map +1 -1
  119. package/lib/typescript/commonjs/sdkVersion.d.ts +1 -1
  120. package/lib/typescript/commonjs/sdkVersion.d.ts.map +1 -1
  121. package/lib/typescript/commonjs/specs/NativeHotUpdater.d.ts +42 -47
  122. package/lib/typescript/commonjs/specs/NativeHotUpdater.d.ts.map +1 -1
  123. package/lib/typescript/commonjs/store.d.ts +1 -3
  124. package/lib/typescript/commonjs/store.d.ts.map +1 -1
  125. package/lib/typescript/commonjs/types.d.ts +1 -1
  126. package/lib/typescript/commonjs/types.d.ts.map +1 -1
  127. package/lib/typescript/commonjs/updateError.d.ts +26 -0
  128. package/lib/typescript/commonjs/updateError.d.ts.map +1 -0
  129. package/lib/typescript/commonjs/wrap.d.ts.map +1 -1
  130. package/lib/typescript/commonjs/wrap.types.d.ts +6 -7
  131. package/lib/typescript/commonjs/wrap.types.d.ts.map +1 -1
  132. package/lib/typescript/module/appReady.d.ts +23 -0
  133. package/lib/typescript/module/appReady.d.ts.map +1 -0
  134. package/lib/typescript/module/checkForUpdate.d.ts +16 -4
  135. package/lib/typescript/module/checkForUpdate.d.ts.map +1 -1
  136. package/lib/typescript/module/clientPlugin.d.ts +2 -0
  137. package/lib/typescript/module/clientPlugin.d.ts.map +1 -0
  138. package/lib/typescript/module/error.d.ts +4 -13
  139. package/lib/typescript/module/error.d.ts.map +1 -1
  140. package/lib/typescript/module/fetchJSON.d.ts +3 -0
  141. package/lib/typescript/module/fetchJSON.d.ts.map +1 -1
  142. package/lib/typescript/module/httpClient.d.ts +3 -32
  143. package/lib/typescript/module/httpClient.d.ts.map +1 -1
  144. package/lib/typescript/module/index.d.ts +7 -12
  145. package/lib/typescript/module/index.d.ts.map +1 -1
  146. package/lib/typescript/module/native.d.ts +33 -23
  147. package/lib/typescript/module/native.d.ts.map +1 -1
  148. package/lib/typescript/module/pluginHost.d.ts +4 -0
  149. package/lib/typescript/module/pluginHost.d.ts.map +1 -0
  150. package/lib/typescript/module/releaseCatalogCache.d.ts +6 -14
  151. package/lib/typescript/module/releaseCatalogCache.d.ts.map +1 -1
  152. package/lib/typescript/module/sdkVersion.d.ts +1 -1
  153. package/lib/typescript/module/sdkVersion.d.ts.map +1 -1
  154. package/lib/typescript/module/specs/NativeHotUpdater.d.ts +42 -47
  155. package/lib/typescript/module/specs/NativeHotUpdater.d.ts.map +1 -1
  156. package/lib/typescript/module/store.d.ts +1 -3
  157. package/lib/typescript/module/store.d.ts.map +1 -1
  158. package/lib/typescript/module/types.d.ts +1 -1
  159. package/lib/typescript/module/types.d.ts.map +1 -1
  160. package/lib/typescript/module/updateError.d.ts +26 -0
  161. package/lib/typescript/module/updateError.d.ts.map +1 -0
  162. package/lib/typescript/module/wrap.d.ts.map +1 -1
  163. package/lib/typescript/module/wrap.types.d.ts +6 -7
  164. package/lib/typescript/module/wrap.types.d.ts.map +1 -1
  165. package/package.json +7 -4
  166. package/src/appReady.ts +149 -0
  167. package/src/checkForUpdate.ts +152 -89
  168. package/src/clientPlugin.ts +17 -0
  169. package/src/error.ts +4 -14
  170. package/src/fetchJSON.ts +5 -1
  171. package/src/httpClient.ts +78 -157
  172. package/src/index.ts +87 -29
  173. package/src/native.ts +109 -104
  174. package/src/pluginHost.ts +45 -0
  175. package/src/releaseCatalogCache.ts +26 -140
  176. package/src/sdkVersion.ts +1 -1
  177. package/src/specs/NativeHotUpdater.ts +41 -48
  178. package/src/store.ts +2 -23
  179. package/src/types.ts +1 -1
  180. package/src/updateError.ts +153 -0
  181. package/src/wrap.tsx +59 -28
  182. package/src/wrap.types.ts +6 -7
  183. package/android/src/main/java/com/hotupdater/DecompressService.kt +0 -89
  184. package/android/src/main/java/com/hotupdater/DecompressionStrategy.kt +0 -26
  185. package/android/src/main/java/com/hotupdater/TarBrDecompressionStrategy.kt +0 -117
  186. package/android/src/main/java/com/hotupdater/TarGzDecompressionStrategy.kt +0 -117
  187. package/android/src/main/java/com/hotupdater/ZipDecompressionStrategy.kt +0 -192
  188. package/android/src/test/java/com/hotupdater/BsdiffPatchTest.kt +0 -46
  189. package/android/src/test/java/com/hotupdater/BundleFileStorageServiceTest.kt +0 -799
  190. package/android/src/test/java/com/hotupdater/HotUpdaterImplTest.kt +0 -273
  191. package/android/src/test/java/com/hotupdater/NativeConfigUtilsTest.kt +0 -20
  192. package/android/src/test/java/com/hotupdater/OkHttpDownloadServiceTest.kt +0 -111
  193. package/android/src/test/java/com/hotupdater/RelativePathResolverTest.kt +0 -41
  194. package/android/src/test/java/com/hotupdater/ReleaseCatalogCacheServiceTest.kt +0 -118
  195. package/android/src/test/java/com/hotupdater/TarArchiveInputStreamTest.kt +0 -68
  196. package/ios/HotUpdater/Internal/ArchiveExtractionUtilities.swift +0 -178
  197. package/ios/HotUpdater/Internal/DecompressService.swift +0 -112
  198. package/ios/HotUpdater/Internal/DecompressionStrategy.swift +0 -22
  199. package/ios/HotUpdater/Internal/StreamingTarArchiveExtractor.swift +0 -370
  200. package/ios/HotUpdater/Internal/TarBrDecompressionStrategy.swift +0 -39
  201. package/ios/HotUpdater/Internal/TarGzDecompressionStrategy.swift +0 -59
  202. package/ios/HotUpdater/Internal/ZipArchiveExtractor.swift +0 -482
  203. package/ios/HotUpdater/Internal/ZipDecompressionStrategy.swift +0 -56
  204. package/lib/commonjs/catalogCacheNative.spec.js +0 -31
  205. package/lib/commonjs/catalogCacheNative.spec.js.map +0 -1
  206. package/lib/commonjs/checkForUpdate.releaseCatalog.spec.js +0 -604
  207. package/lib/commonjs/checkForUpdate.releaseCatalog.spec.js.map +0 -1
  208. package/lib/commonjs/httpClient.spec.js +0 -102
  209. package/lib/commonjs/httpClient.spec.js.map +0 -1
  210. package/lib/commonjs/index.spec.js +0 -298
  211. package/lib/commonjs/index.spec.js.map +0 -1
  212. package/lib/commonjs/iosInterop.spec.js +0 -18
  213. package/lib/commonjs/iosInterop.spec.js.map +0 -1
  214. package/lib/commonjs/native.spec.js +0 -795
  215. package/lib/commonjs/native.spec.js.map +0 -1
  216. package/lib/commonjs/notifyAppReadyInsights.boundary.spec.js +0 -218
  217. package/lib/commonjs/notifyAppReadyInsights.boundary.spec.js.map +0 -1
  218. package/lib/commonjs/notifyAppReadyInsights.js +0 -133
  219. package/lib/commonjs/notifyAppReadyInsights.js.map +0 -1
  220. package/lib/commonjs/notifyAppReadyInsights.spec.js +0 -246
  221. package/lib/commonjs/notifyAppReadyInsights.spec.js.map +0 -1
  222. package/lib/commonjs/notifyAppReadyInsights.test-utils.js +0 -24
  223. package/lib/commonjs/notifyAppReadyInsights.test-utils.js.map +0 -1
  224. package/lib/commonjs/notifyAppReadyInsights.transport.spec.js +0 -117
  225. package/lib/commonjs/notifyAppReadyInsights.transport.spec.js.map +0 -1
  226. package/lib/commonjs/releaseCatalogCache.spec.js +0 -195
  227. package/lib/commonjs/releaseCatalogCache.spec.js.map +0 -1
  228. package/lib/commonjs/releaseCatalogCacheNativeContract.spec.js +0 -64
  229. package/lib/commonjs/releaseCatalogCacheNativeContract.spec.js.map +0 -1
  230. package/lib/commonjs/store.notification.spec.js +0 -76
  231. package/lib/commonjs/store.notification.spec.js.map +0 -1
  232. package/lib/commonjs/store.spec.js +0 -316
  233. package/lib/commonjs/store.spec.js.map +0 -1
  234. package/lib/commonjs/wrap.spec.js +0 -296
  235. package/lib/commonjs/wrap.spec.js.map +0 -1
  236. package/lib/module/catalogCacheNative.spec.js +0 -31
  237. package/lib/module/catalogCacheNative.spec.js.map +0 -1
  238. package/lib/module/checkForUpdate.releaseCatalog.spec.js +0 -603
  239. package/lib/module/checkForUpdate.releaseCatalog.spec.js.map +0 -1
  240. package/lib/module/httpClient.spec.js +0 -102
  241. package/lib/module/httpClient.spec.js.map +0 -1
  242. package/lib/module/index.spec.js +0 -297
  243. package/lib/module/index.spec.js.map +0 -1
  244. package/lib/module/iosInterop.spec.js +0 -18
  245. package/lib/module/iosInterop.spec.js.map +0 -1
  246. package/lib/module/native.spec.js +0 -794
  247. package/lib/module/native.spec.js.map +0 -1
  248. package/lib/module/notifyAppReadyInsights.boundary.spec.js +0 -217
  249. package/lib/module/notifyAppReadyInsights.boundary.spec.js.map +0 -1
  250. package/lib/module/notifyAppReadyInsights.js +0 -128
  251. package/lib/module/notifyAppReadyInsights.js.map +0 -1
  252. package/lib/module/notifyAppReadyInsights.spec.js +0 -245
  253. package/lib/module/notifyAppReadyInsights.spec.js.map +0 -1
  254. package/lib/module/notifyAppReadyInsights.test-utils.js +0 -18
  255. package/lib/module/notifyAppReadyInsights.test-utils.js.map +0 -1
  256. package/lib/module/notifyAppReadyInsights.transport.spec.js +0 -116
  257. package/lib/module/notifyAppReadyInsights.transport.spec.js.map +0 -1
  258. package/lib/module/releaseCatalogCache.spec.js +0 -195
  259. package/lib/module/releaseCatalogCache.spec.js.map +0 -1
  260. package/lib/module/releaseCatalogCacheNativeContract.spec.js +0 -64
  261. package/lib/module/releaseCatalogCacheNativeContract.spec.js.map +0 -1
  262. package/lib/module/store.notification.spec.js +0 -77
  263. package/lib/module/store.notification.spec.js.map +0 -1
  264. package/lib/module/store.spec.js +0 -315
  265. package/lib/module/store.spec.js.map +0 -1
  266. package/lib/module/wrap.spec.js +0 -295
  267. package/lib/module/wrap.spec.js.map +0 -1
  268. package/lib/typescript/commonjs/notifyAppReadyInsights.d.ts +0 -13
  269. package/lib/typescript/commonjs/notifyAppReadyInsights.d.ts.map +0 -1
  270. package/lib/typescript/commonjs/notifyAppReadyInsights.test-utils.d.ts +0 -8
  271. package/lib/typescript/commonjs/notifyAppReadyInsights.test-utils.d.ts.map +0 -1
  272. package/lib/typescript/module/notifyAppReadyInsights.d.ts +0 -13
  273. package/lib/typescript/module/notifyAppReadyInsights.d.ts.map +0 -1
  274. package/lib/typescript/module/notifyAppReadyInsights.test-utils.d.ts +0 -8
  275. package/lib/typescript/module/notifyAppReadyInsights.test-utils.d.ts.map +0 -1
  276. package/src/catalogCacheNative.spec.ts +0 -63
  277. package/src/checkForUpdate.releaseCatalog.spec.ts +0 -596
  278. package/src/httpClient.spec.ts +0 -132
  279. package/src/index.spec.ts +0 -331
  280. package/src/iosInterop.spec.ts +0 -30
  281. package/src/native.spec.ts +0 -855
  282. package/src/notifyAppReadyInsights.boundary.spec.ts +0 -234
  283. package/src/notifyAppReadyInsights.spec.ts +0 -243
  284. package/src/notifyAppReadyInsights.test-utils.ts +0 -31
  285. package/src/notifyAppReadyInsights.transport.spec.ts +0 -130
  286. package/src/notifyAppReadyInsights.ts +0 -194
  287. package/src/releaseCatalogCache.spec.ts +0 -282
  288. package/src/releaseCatalogCacheNativeContract.spec.ts +0 -80
  289. package/src/store.notification.spec.ts +0 -92
  290. package/src/store.spec.ts +0 -372
  291. package/src/wrap.spec.ts +0 -367
@@ -1,13 +0,0 @@
1
- import type { HotUpdaterError } from "./error";
2
- import type { HotUpdaterHttpClient } from "./httpClient";
3
- import { type NotifyAppReadyResult } from "./native";
4
- export type NotifyAppReadyOptions = {
5
- insights?: boolean;
6
- client: HotUpdaterHttpClient;
7
- requestHeaders?: Record<string, string>;
8
- requestTimeout?: number;
9
- onNotifyAppReady?: (result: NotifyAppReadyResult) => void;
10
- onError?: (error: HotUpdaterError | Error | unknown) => void;
11
- };
12
- export declare const handleNotifyAppReady: (options: NotifyAppReadyOptions) => Promise<void>;
13
- //# sourceMappingURL=notifyAppReadyInsights.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"notifyAppReadyInsights.d.ts","sourceRoot":"","sources":["../../../src/notifyAppReadyInsights.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,EAAuB,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAC9E,OAAO,EASL,KAAK,oBAAoB,EAE1B,MAAM,UAAU,CAAC;AAElB,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,oBAAoB,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAC1D,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,GAAG,KAAK,GAAG,OAAO,KAAK,IAAI,CAAC;CAC9D,CAAC;AA4IF,eAAO,MAAM,oBAAoB,YACtB,qBAAqB,KAC7B,OAAO,CAAC,IAAI,CA2Bd,CAAC"}
@@ -1,8 +0,0 @@
1
- import type { NotifyAppReadyInsightsEvent, NotifyAppReadyResult } from "./native";
2
- export declare const createNotifyReadResult: (result?: NotifyAppReadyResult, insightsEvent?: NotifyAppReadyInsightsEvent | null, pending?: boolean) => {
3
- insightsEvent: NotifyAppReadyInsightsEvent | null;
4
- pending: boolean;
5
- result: NotifyAppReadyResult;
6
- };
7
- export declare const stubNotifyFrame: () => void;
8
- //# sourceMappingURL=notifyAppReadyInsights.test-utils.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"notifyAppReadyInsights.test-utils.d.ts","sourceRoot":"","sources":["../../../src/notifyAppReadyInsights.test-utils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,2BAA2B,EAC3B,oBAAoB,EACrB,MAAM,UAAU,CAAC;AAElB,eAAO,MAAM,sBAAsB,YACzB,oBAAoB,kBACb,2BAA2B,GAAG,IAAI,wBAEhD;IACD,aAAa,EAAE,2BAA2B,GAAG,IAAI,CAAC;IAClD,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,oBAAoB,CAAC;CAK7B,CAAC;AAEH,eAAO,MAAM,eAAe,YAS3B,CAAC"}
@@ -1,63 +0,0 @@
1
- import { beforeEach, describe, expect, it, vi } from "vitest";
2
-
3
- const nativeModule = vi.hoisted(
4
- () => ({}) as Record<string, ReturnType<typeof vi.fn>>,
5
- );
6
-
7
- vi.mock("./specs/NativeHotUpdater", () => ({ default: nativeModule }));
8
-
9
- import {
10
- readNativeReleaseCatalogCache,
11
- removeNativeReleaseCatalogCache,
12
- writeNativeReleaseCatalogCache,
13
- } from "./catalogCacheNative";
14
-
15
- describe("Release Catalog native cache", () => {
16
- beforeEach(() => {
17
- for (const key of Object.keys(nativeModule)) delete nativeModule[key];
18
- });
19
-
20
- it("fails fast when the v1 native cache API is missing", async () => {
21
- await expect(readNativeReleaseCatalogCache("partition")).rejects.toThrow(
22
- "Native module is missing 'getReleaseCatalogCache()'. Rebuild the native app before using Release catalogs.",
23
- );
24
- await expect(
25
- writeNativeReleaseCatalogCache("partition", "payload"),
26
- ).rejects.toThrow(
27
- "Native module is missing 'setReleaseCatalogCache()'. Rebuild the native app before using Release catalogs.",
28
- );
29
- await expect(removeNativeReleaseCatalogCache("partition")).rejects.toThrow(
30
- "Native module is missing 'removeReleaseCatalogCache()'. Rebuild the native app before using Release catalogs.",
31
- );
32
- });
33
-
34
- it("normalizes an undefined iOS TurboModule cache miss to null", async () => {
35
- nativeModule.getReleaseCatalogCache = vi.fn().mockResolvedValue(undefined);
36
-
37
- await expect(
38
- readNativeReleaseCatalogCache("partition"),
39
- ).resolves.toBeNull();
40
- });
41
-
42
- it("treats native cache I/O failures as misses without hiding network work", async () => {
43
- nativeModule.getReleaseCatalogCache = vi
44
- .fn()
45
- .mockRejectedValue(new Error("read"));
46
- nativeModule.setReleaseCatalogCache = vi
47
- .fn()
48
- .mockRejectedValue(new Error("write"));
49
- nativeModule.removeReleaseCatalogCache = vi
50
- .fn()
51
- .mockRejectedValue(new Error("remove"));
52
-
53
- await expect(
54
- readNativeReleaseCatalogCache("partition"),
55
- ).resolves.toBeNull();
56
- await expect(
57
- writeNativeReleaseCatalogCache("partition", "payload"),
58
- ).resolves.toBe(false);
59
- await expect(
60
- removeNativeReleaseCatalogCache("partition"),
61
- ).resolves.toBeUndefined();
62
- });
63
- });
@@ -1,596 +0,0 @@
1
- import {
2
- createReleaseCatalogScopeKey,
3
- encodeChannelKey,
4
- type PersistedSelectionReceipt,
5
- type ReleaseCatalog,
6
- } from "@hot-updater/core";
7
- import { beforeEach, describe, expect, it, vi } from "vitest";
8
-
9
- import type { HotUpdaterHttpClient } from "./httpClient";
10
-
11
- const MINIMUM_RELEASE_ID = "00000000-0000-7000-8000-000000000001";
12
- const RELEASE_ID = "00000000-0000-7000-8000-000000000002";
13
- const ACTIVE_RELEASE_ID = "00000000-0000-7000-8000-000000000003";
14
- const CURRENT_BUNDLE_ID = "00000000-0000-7001-8000-000000000001";
15
- const TARGET_BUNDLE_ID = "00000000-0000-7001-8000-000000000002";
16
- const CATALOG_ID = "project-a";
17
- const CHANNEL = "production";
18
- const CATALOG_HASH = `sha256:${"a".repeat(64)}`;
19
- const SCOPE_KEY = createReleaseCatalogScopeKey({
20
- channelKey: encodeChannelKey(CHANNEL),
21
- platform: "ios",
22
- strategy: "APP_VERSION",
23
- });
24
-
25
- const mocks = vi.hoisted(() => ({
26
- addListener: vi.fn(() => () => {}),
27
- acceptReleaseCatalog: vi.fn(() => true),
28
- commitReleaseSelection: vi.fn(async () => true),
29
- getActiveUpdateState: vi.fn(() => ({
30
- activeSelection: null as PersistedSelectionReceipt | null,
31
- highestSeenCatalogs: {},
32
- stableSelection: null as PersistedSelectionReceipt | null,
33
- verificationPending: false,
34
- })),
35
- getAppVersion: vi.fn(() => "1.2"),
36
- getBundleId: vi.fn(() => CURRENT_BUNDLE_ID),
37
- getChannel: vi.fn(() => CHANNEL),
38
- getCohort: vi.fn(() => "123"),
39
- getCrashHistory: vi.fn(() => []),
40
- getDefaultChannel: vi.fn(() => CHANNEL),
41
- getFingerprintHash: vi.fn(() => null),
42
- getInstallId: vi.fn(() => "install-id"),
43
- getMinBundleId: vi.fn(() => MINIMUM_RELEASE_ID),
44
- getPersistedUserIdentity: vi.fn(() => ({})),
45
- isChannelSwitched: vi.fn(() => false),
46
- isReleaseSelectionCurrent: vi.fn(() => true),
47
- resetChannel: vi.fn(),
48
- updateBundle: vi.fn(async () => true),
49
- }));
50
-
51
- vi.mock("react-native", () => ({ Platform: { OS: "ios" } }));
52
-
53
- vi.mock("./native", () => mocks);
54
-
55
- const createCatalog = (
56
- overrides: Partial<ReleaseCatalog> = {},
57
- ): ReleaseCatalog => ({
58
- catalogId: CATALOG_ID,
59
- catalogHash: CATALOG_HASH,
60
- fallbackPolicy: "BUILTIN_IF_ACTIVE_INELIGIBLE",
61
- generation: 2,
62
- releases: [
63
- {
64
- bundleId: TARGET_BUNDLE_ID,
65
- kind: "BUNDLE",
66
- message: "Release two",
67
- releaseId: RELEASE_ID,
68
- rolloutCohortCount: 1000,
69
- shouldForceUpdate: false,
70
- targetCohorts: [],
71
- },
72
- ],
73
- schemaVersion: 1,
74
- scopeKey: SCOPE_KEY,
75
- ...overrides,
76
- });
77
-
78
- const createClient = (catalog = createCatalog()) => {
79
- const fetchReleaseCatalog = vi.fn(async () => catalog);
80
- const resolveArtifact = vi.fn(async () => ({
81
- fileHash: "bundle-hash",
82
- fileUrl: "https://updates.example.com/bundle.zip",
83
- }));
84
- const sendInsightsEvent = vi.fn(async () => undefined);
85
- const session = {
86
- fetchReleaseCatalog,
87
- resolveArtifact,
88
- sendInsightsEvent,
89
- };
90
- const client: HotUpdaterHttpClient = {
91
- createSession: vi.fn(async () => session),
92
- };
93
- return { client, fetchReleaseCatalog, resolveArtifact, sendInsightsEvent };
94
- };
95
-
96
- describe("checkForUpdate Release catalog protocol", () => {
97
- beforeEach(() => {
98
- vi.clearAllMocks();
99
- vi.stubGlobal("__DEV__", false);
100
- mocks.acceptReleaseCatalog.mockReturnValue(true);
101
- mocks.getActiveUpdateState.mockReturnValue({
102
- activeSelection: null,
103
- highestSeenCatalogs: {},
104
- stableSelection: null,
105
- verificationPending: false,
106
- });
107
- mocks.isReleaseSelectionCurrent.mockReturnValue(true);
108
- mocks.commitReleaseSelection.mockResolvedValue(true);
109
- mocks.updateBundle.mockResolvedValue(true);
110
- });
111
-
112
- it("selects locally and defers Bundle artifact resolution until install", async () => {
113
- const { checkForUpdate } = await import("./checkForUpdate");
114
- const { client, fetchReleaseCatalog, resolveArtifact } = createClient();
115
-
116
- const result = await checkForUpdate({
117
- client,
118
- updateStrategy: "appVersion",
119
- });
120
-
121
- expect(result).toMatchObject({
122
- id: TARGET_BUNDLE_ID,
123
- releaseId: RELEASE_ID,
124
- transitionKind: "INSTALL",
125
- });
126
- expect(fetchReleaseCatalog).toHaveBeenCalledWith({
127
- appVersion: "1.2.0",
128
- channel: CHANNEL,
129
- fingerprintHash: null,
130
- platform: "ios",
131
- requestHeaders: undefined,
132
- requestTimeout: undefined,
133
- updateStrategy: "appVersion",
134
- });
135
- expect(resolveArtifact).not.toHaveBeenCalled();
136
-
137
- await expect(result?.updateBundle()).resolves.toBe(true);
138
-
139
- expect(resolveArtifact).toHaveBeenCalledWith({
140
- currentBundleId: CURRENT_BUNDLE_ID,
141
- requestHeaders: undefined,
142
- requestTimeout: undefined,
143
- targetBundleId: TARGET_BUNDLE_ID,
144
- });
145
- expect(mocks.updateBundle).toHaveBeenCalledWith(
146
- expect.objectContaining({
147
- bundleId: TARGET_BUNDLE_ID,
148
- selection: expect.objectContaining({
149
- catalogId: CATALOG_ID,
150
- releaseId: RELEASE_ID,
151
- scopeKey: SCOPE_KEY,
152
- }),
153
- }),
154
- );
155
- });
156
-
157
- it("adopts a newer Release for the same Bundle without resolving bytes", async () => {
158
- const active: PersistedSelectionReceipt = {
159
- catalogId: CATALOG_ID,
160
- bundleId: TARGET_BUNDLE_ID,
161
- catalogHash: `sha256:${"b".repeat(64)}`,
162
- channel: CHANNEL,
163
- generation: 1,
164
- kind: "BUNDLE",
165
- releaseId: MINIMUM_RELEASE_ID,
166
- scopeKey: SCOPE_KEY,
167
- selectionContextHash: "old-context",
168
- };
169
- mocks.getBundleId.mockReturnValueOnce(TARGET_BUNDLE_ID);
170
- mocks.getActiveUpdateState.mockReturnValueOnce({
171
- activeSelection: active,
172
- highestSeenCatalogs: {},
173
- stableSelection: active,
174
- verificationPending: false,
175
- });
176
- const { checkForUpdate } = await import("./checkForUpdate");
177
- const forceCatalog = createCatalog({
178
- releases: [
179
- {
180
- ...createCatalog().releases[0]!,
181
- shouldForceUpdate: true,
182
- },
183
- ],
184
- });
185
- const { client, resolveArtifact, sendInsightsEvent } =
186
- createClient(forceCatalog);
187
-
188
- const result = await checkForUpdate({
189
- client,
190
- updateStrategy: "appVersion",
191
- });
192
-
193
- expect(result).toMatchObject({
194
- shouldForceUpdate: false,
195
- transitionKind: "ADOPT_RELEASE",
196
- });
197
- await expect(result?.updateBundle()).resolves.toBe(true);
198
- expect(resolveArtifact).not.toHaveBeenCalled();
199
- expect(mocks.updateBundle).not.toHaveBeenCalled();
200
- expect(sendInsightsEvent).not.toHaveBeenCalled();
201
- expect(mocks.commitReleaseSelection).toHaveBeenCalledWith({
202
- guard: expect.objectContaining({ generation: 2, scopeKey: SCOPE_KEY }),
203
- selection: expect.objectContaining({
204
- bundleId: TARGET_BUNDLE_ID,
205
- releaseId: RELEASE_ID,
206
- }),
207
- });
208
- });
209
-
210
- it("sends RELEASE_ADOPTED only when insights is enabled", async () => {
211
- const active: PersistedSelectionReceipt = {
212
- catalogId: CATALOG_ID,
213
- bundleId: TARGET_BUNDLE_ID,
214
- catalogHash: `sha256:${"b".repeat(64)}`,
215
- channel: CHANNEL,
216
- generation: 1,
217
- kind: "BUNDLE",
218
- releaseId: MINIMUM_RELEASE_ID,
219
- scopeKey: SCOPE_KEY,
220
- selectionContextHash: "old-context",
221
- };
222
- mocks.getBundleId.mockReturnValueOnce(TARGET_BUNDLE_ID);
223
- mocks.getActiveUpdateState.mockReturnValueOnce({
224
- activeSelection: active,
225
- highestSeenCatalogs: {},
226
- stableSelection: active,
227
- verificationPending: false,
228
- });
229
- const { checkForUpdate } = await import("./checkForUpdate");
230
- const { client, sendInsightsEvent } = createClient();
231
-
232
- const result = await checkForUpdate({
233
- insights: true,
234
- client,
235
- updateStrategy: "appVersion",
236
- });
237
- await result?.updateBundle();
238
-
239
- expect(sendInsightsEvent).toHaveBeenCalledWith(
240
- expect.objectContaining({
241
- fromReleaseId: MINIMUM_RELEASE_ID,
242
- toReleaseId: RELEASE_ID,
243
- type: "RELEASE_ADOPTED",
244
- }),
245
- );
246
- });
247
-
248
- it("selects a lower-id Release when explicitly switching scopes", async () => {
249
- const betaChannel = "beta";
250
- const betaScopeKey = createReleaseCatalogScopeKey({
251
- channelKey: encodeChannelKey(betaChannel),
252
- platform: "ios",
253
- strategy: "APP_VERSION",
254
- });
255
- const active: PersistedSelectionReceipt = {
256
- catalogId: CATALOG_ID,
257
- bundleId: CURRENT_BUNDLE_ID,
258
- catalogHash: `sha256:${"b".repeat(64)}`,
259
- channel: CHANNEL,
260
- generation: 1,
261
- kind: "BUNDLE",
262
- releaseId: ACTIVE_RELEASE_ID,
263
- scopeKey: SCOPE_KEY,
264
- selectionContextHash: "old-context",
265
- };
266
- mocks.getActiveUpdateState.mockReturnValueOnce({
267
- activeSelection: active,
268
- highestSeenCatalogs: {},
269
- stableSelection: active,
270
- verificationPending: false,
271
- });
272
- const betaCatalog = createCatalog({ scopeKey: betaScopeKey });
273
- const { checkForUpdate } = await import("./checkForUpdate");
274
- const { client } = createClient(betaCatalog);
275
-
276
- const result = await checkForUpdate({
277
- channel: betaChannel,
278
- client,
279
- updateStrategy: "appVersion",
280
- });
281
-
282
- expect(result).toMatchObject({
283
- id: TARGET_BUNDLE_ID,
284
- releaseId: RELEASE_ID,
285
- status: "UPDATE",
286
- transitionKind: "INSTALL",
287
- });
288
- });
289
-
290
- it("refreshes the same Release receipt when catalog provenance changes", async () => {
291
- const active: PersistedSelectionReceipt = {
292
- catalogId: CATALOG_ID,
293
- bundleId: TARGET_BUNDLE_ID,
294
- catalogHash: `sha256:${"b".repeat(64)}`,
295
- channel: CHANNEL,
296
- generation: 1,
297
- kind: "BUNDLE",
298
- releaseId: RELEASE_ID,
299
- scopeKey: SCOPE_KEY,
300
- selectionContextHash: "old-context",
301
- };
302
- mocks.getBundleId.mockReturnValueOnce(TARGET_BUNDLE_ID);
303
- mocks.getActiveUpdateState.mockReturnValueOnce({
304
- activeSelection: active,
305
- highestSeenCatalogs: {},
306
- stableSelection: active,
307
- verificationPending: false,
308
- });
309
- const { checkForUpdate } = await import("./checkForUpdate");
310
- const { client, resolveArtifact } = createClient();
311
-
312
- const result = await checkForUpdate({
313
- client,
314
- updateStrategy: "appVersion",
315
- });
316
-
317
- expect(result).toMatchObject({
318
- id: TARGET_BUNDLE_ID,
319
- releaseId: RELEASE_ID,
320
- transitionKind: "ADOPT_RELEASE",
321
- });
322
- await expect(result?.updateBundle()).resolves.toBe(true);
323
- expect(resolveArtifact).not.toHaveBeenCalled();
324
- expect(mocks.updateBundle).not.toHaveBeenCalled();
325
- expect(mocks.commitReleaseSelection).toHaveBeenCalledWith({
326
- guard: expect.objectContaining({
327
- catalogHash: CATALOG_HASH,
328
- generation: 2,
329
- scopeKey: SCOPE_KEY,
330
- }),
331
- selection: expect.objectContaining({
332
- bundleId: TARGET_BUNDLE_ID,
333
- catalogHash: CATALOG_HASH,
334
- generation: 2,
335
- releaseId: RELEASE_ID,
336
- }),
337
- });
338
- });
339
-
340
- it("rejects a slow artifact completion after a newer catalog wins", async () => {
341
- mocks.isReleaseSelectionCurrent
342
- .mockReturnValueOnce(true)
343
- .mockReturnValueOnce(false);
344
- const { StaleReleaseCatalogError } = await import("./error");
345
- const { checkForUpdate } = await import("./checkForUpdate");
346
- const { client } = createClient();
347
- const result = await checkForUpdate({
348
- client,
349
- updateStrategy: "appVersion",
350
- });
351
-
352
- await expect(result?.updateBundle()).rejects.toBeInstanceOf(
353
- StaleReleaseCatalogError,
354
- );
355
- expect(mocks.updateBundle).not.toHaveBeenCalled();
356
- });
357
-
358
- it("installs an older enabled Release as a forced rollback", async () => {
359
- const active: PersistedSelectionReceipt = {
360
- catalogId: CATALOG_ID,
361
- bundleId: CURRENT_BUNDLE_ID,
362
- catalogHash: `sha256:${"b".repeat(64)}`,
363
- channel: CHANNEL,
364
- generation: 1,
365
- kind: "BUNDLE",
366
- releaseId: ACTIVE_RELEASE_ID,
367
- scopeKey: SCOPE_KEY,
368
- selectionContextHash: "old-context",
369
- };
370
- mocks.getActiveUpdateState.mockReturnValueOnce({
371
- activeSelection: active,
372
- highestSeenCatalogs: {},
373
- stableSelection: active,
374
- verificationPending: false,
375
- });
376
- const catalog = createCatalog({
377
- rollbackReleases: [
378
- {
379
- bundleId: TARGET_BUNDLE_ID,
380
- kind: "BUNDLE",
381
- message: "Previous Release",
382
- releaseId: RELEASE_ID,
383
- rolloutCohortCount: 0,
384
- shouldForceUpdate: false,
385
- targetCohorts: [],
386
- },
387
- ],
388
- });
389
- const { checkForUpdate } = await import("./checkForUpdate");
390
- const { client } = createClient(catalog);
391
-
392
- const result = await checkForUpdate({
393
- client,
394
- updateStrategy: "appVersion",
395
- });
396
-
397
- expect(result).toMatchObject({
398
- id: TARGET_BUNDLE_ID,
399
- releaseId: RELEASE_ID,
400
- shouldForceUpdate: true,
401
- status: "ROLLBACK",
402
- transitionKind: "INSTALL",
403
- });
404
- await expect(result?.updateBundle()).resolves.toBe(true);
405
- expect(mocks.updateBundle).toHaveBeenCalledWith(
406
- expect.objectContaining({
407
- bundleId: TARGET_BUNDLE_ID,
408
- status: "ROLLBACK",
409
- }),
410
- );
411
- });
412
-
413
- it("uses current Bundle identity when migrating an unauthenticated receipt", async () => {
414
- const migratedCurrentBundleId = "00000000-0000-7001-8000-000000000003";
415
- const active: PersistedSelectionReceipt = {
416
- catalogId: null,
417
- bundleId: migratedCurrentBundleId,
418
- catalogHash: null,
419
- channel: CHANNEL,
420
- generation: null,
421
- kind: "BUNDLE",
422
- releaseId: null,
423
- scopeKey: null,
424
- selectionContextHash: null,
425
- };
426
- mocks.getBundleId.mockReturnValueOnce(migratedCurrentBundleId);
427
- mocks.getActiveUpdateState.mockReturnValueOnce({
428
- activeSelection: active,
429
- highestSeenCatalogs: {},
430
- stableSelection: active,
431
- verificationPending: false,
432
- });
433
- const catalog = createCatalog({
434
- releases: [],
435
- rollbackReleases: [
436
- {
437
- ...createCatalog().releases[0]!,
438
- rolloutCohortCount: 0,
439
- },
440
- ],
441
- });
442
- const { checkForUpdate } = await import("./checkForUpdate");
443
- const { client } = createClient(catalog);
444
-
445
- const result = await checkForUpdate({
446
- client,
447
- updateStrategy: "appVersion",
448
- });
449
-
450
- expect(result).toMatchObject({
451
- id: TARGET_BUNDLE_ID,
452
- shouldForceUpdate: true,
453
- status: "ROLLBACK",
454
- transitionKind: "INSTALL",
455
- });
456
- });
457
-
458
- it("returns a forced built-in rollback only for an active OTA", async () => {
459
- const active: PersistedSelectionReceipt = {
460
- catalogId: CATALOG_ID,
461
- bundleId: CURRENT_BUNDLE_ID,
462
- catalogHash: `sha256:${"b".repeat(64)}`,
463
- channel: CHANNEL,
464
- generation: 1,
465
- kind: "BUNDLE",
466
- releaseId: ACTIVE_RELEASE_ID,
467
- scopeKey: SCOPE_KEY,
468
- selectionContextHash: "old-context",
469
- };
470
- mocks.getActiveUpdateState.mockReturnValueOnce({
471
- activeSelection: active,
472
- highestSeenCatalogs: {},
473
- stableSelection: active,
474
- verificationPending: false,
475
- });
476
- const { checkForUpdate } = await import("./checkForUpdate");
477
- const { client } = createClient(
478
- createCatalog({ releases: [], rollbackReleases: [] }),
479
- );
480
-
481
- const result = await checkForUpdate({
482
- client,
483
- updateStrategy: "appVersion",
484
- });
485
-
486
- expect(result).toMatchObject({
487
- id: MINIMUM_RELEASE_ID,
488
- releaseId: null,
489
- shouldForceUpdate: true,
490
- status: "ROLLBACK",
491
- transitionKind: "USE_BUILTIN",
492
- });
493
- await expect(result?.updateBundle()).resolves.toBe(true);
494
- expect(mocks.commitReleaseSelection).toHaveBeenCalledWith(
495
- expect.objectContaining({
496
- selection: expect.objectContaining({
497
- kind: "BUILTIN",
498
- releaseId: null,
499
- }),
500
- }),
501
- );
502
- });
503
-
504
- it("does not surface a rollback when the app already uses built-in bytes", async () => {
505
- mocks.getBundleId.mockReturnValueOnce(MINIMUM_RELEASE_ID);
506
- const { checkForUpdate } = await import("./checkForUpdate");
507
- const { client } = createClient(
508
- createCatalog({ releases: [], rollbackReleases: [] }),
509
- );
510
-
511
- await expect(
512
- checkForUpdate({ client, updateStrategy: "appVersion" }),
513
- ).resolves.toBeNull();
514
- expect(mocks.commitReleaseSelection).not.toHaveBeenCalled();
515
- });
516
-
517
- it("reports a rejected generation without selecting or resolving artifacts", async () => {
518
- mocks.acceptReleaseCatalog.mockReturnValueOnce(false);
519
- const onError = vi.fn();
520
- const { checkForUpdate } = await import("./checkForUpdate");
521
- const { client, resolveArtifact } = createClient();
522
-
523
- await expect(
524
- checkForUpdate({ client, onError, updateStrategy: "appVersion" }),
525
- ).resolves.toBeNull();
526
-
527
- expect(onError).toHaveBeenCalledWith(
528
- expect.objectContaining({
529
- message: "Rejected a stale or inconsistent Release catalog",
530
- }),
531
- );
532
- expect(resolveArtifact).not.toHaveBeenCalled();
533
- });
534
-
535
- it("rejects mismatched catalog scope before native catalog state mutates", async () => {
536
- const wrongScope = createReleaseCatalogScopeKey({
537
- channelKey: encodeChannelKey("beta"),
538
- platform: "ios",
539
- strategy: "APP_VERSION",
540
- });
541
- const onError = vi.fn();
542
- const { checkForUpdate } = await import("./checkForUpdate");
543
- const { client } = createClient(createCatalog({ scopeKey: wrongScope }));
544
-
545
- await expect(
546
- checkForUpdate({ client, onError, updateStrategy: "appVersion" }),
547
- ).resolves.toBeNull();
548
-
549
- expect(onError).toHaveBeenCalledWith(
550
- expect.objectContaining({
551
- message: "Received an invalid Release catalog",
552
- }),
553
- );
554
- expect(mocks.acceptReleaseCatalog).not.toHaveBeenCalled();
555
- expect(mocks.commitReleaseSelection).not.toHaveBeenCalled();
556
- expect(mocks.updateBundle).not.toHaveBeenCalled();
557
- });
558
-
559
- it("rejects an unexpected Catalog identity before accepting catalog state", async () => {
560
- const active: PersistedSelectionReceipt = {
561
- catalogId: "existing-project",
562
- bundleId: CURRENT_BUNDLE_ID,
563
- catalogHash: `sha256:${"b".repeat(64)}`,
564
- channel: CHANNEL,
565
- generation: 1,
566
- kind: "BUNDLE",
567
- releaseId: ACTIVE_RELEASE_ID,
568
- scopeKey: createReleaseCatalogScopeKey({
569
- channelKey: encodeChannelKey(CHANNEL),
570
- platform: "ios",
571
- strategy: "APP_VERSION",
572
- }),
573
- selectionContextHash: "old-context",
574
- };
575
- mocks.getActiveUpdateState.mockReturnValueOnce({
576
- activeSelection: active,
577
- highestSeenCatalogs: {},
578
- stableSelection: active,
579
- verificationPending: false,
580
- });
581
- const onError = vi.fn();
582
- const { checkForUpdate } = await import("./checkForUpdate");
583
- const { client } = createClient();
584
-
585
- await expect(
586
- checkForUpdate({ client, onError, updateStrategy: "appVersion" }),
587
- ).resolves.toBeNull();
588
-
589
- expect(onError).toHaveBeenCalledWith(
590
- expect.objectContaining({
591
- message: "Release transition rejected: UNSOLICITED_SCOPE",
592
- }),
593
- );
594
- expect(mocks.acceptReleaseCatalog).not.toHaveBeenCalled();
595
- });
596
- });