@hot-updater/react-native 1.0.0-rc.4 → 1.0.0-rc.40

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 (306) hide show
  1. package/android/build.gradle +13 -2
  2. package/android/proguard-rules.pro +8 -2
  3. package/android/src/bridge/BridgeReactInstance.kt +38 -0
  4. package/android/src/bridgeless/BridgeReactInstance.kt +24 -0
  5. package/android/src/main/java/com/hotupdater/ActivityStartGate.kt +94 -0
  6. package/android/src/main/java/com/hotupdater/BuiltInAssetResolver.kt +286 -0
  7. package/android/src/main/java/com/hotupdater/BundleFileStorageService.kt +1064 -844
  8. package/android/src/main/java/com/hotupdater/BundleMetadata.kt +50 -11
  9. package/android/src/main/java/com/hotupdater/FileManagerService.kt +45 -0
  10. package/android/src/main/java/com/hotupdater/HotUpdaterException.kt +287 -22
  11. package/android/src/main/java/com/hotupdater/HotUpdaterImpl.kt +46 -30
  12. package/android/src/main/java/com/hotupdater/HotUpdaterRecoveryManager.kt +75 -192
  13. package/android/src/main/java/com/hotupdater/HotUpdaterRecoveryState.kt +64 -0
  14. package/android/src/main/java/com/hotupdater/InstallIdentityService.kt +37 -0
  15. package/android/src/main/java/com/hotupdater/KeyValueStorageService.kt +86 -0
  16. package/android/src/main/java/com/hotupdater/NetworkState.kt +31 -0
  17. package/android/src/main/java/com/hotupdater/NoBackupStorage.kt +17 -0
  18. package/android/src/main/java/com/hotupdater/OkHttpDownloadService.kt +127 -50
  19. package/android/src/main/java/com/hotupdater/ReactNativeValueConverters.kt +34 -0
  20. package/android/src/main/java/com/hotupdater/TarArchiveInputStream.kt +214 -375
  21. package/android/src/main/java/com/hotupdater/TarBrArchiveExtractor.kt +119 -0
  22. package/android/src/newarch/HotUpdater.kt +7 -9
  23. package/android/src/newarch/HotUpdaterModule.kt +109 -84
  24. package/android/src/newarch/JavaScriptExceptionHooks.kt +48 -0
  25. package/android/src/newarch/ReactIntegrationManager.kt +6 -32
  26. package/android/src/oldarch/HotUpdater.kt +7 -9
  27. package/android/src/oldarch/HotUpdaterModule.kt +98 -74
  28. package/android/src/oldarch/HotUpdaterSpec.kt +4 -6
  29. package/android/src/oldarch/JavaScriptExceptionHooks.kt +71 -0
  30. package/ios/HotUpdater/Internal/BrotliFileDecompressor.swift +167 -0
  31. package/ios/HotUpdater/Internal/BuiltInAssetResolver.swift +196 -0
  32. package/ios/HotUpdater/Internal/BundleFileStorageService.swift +1032 -1116
  33. package/ios/HotUpdater/Internal/BundleMetadata.swift +61 -54
  34. package/ios/HotUpdater/Internal/FileManagerService.swift +48 -0
  35. package/ios/HotUpdater/Internal/FileUtilities.swift +64 -0
  36. package/ios/HotUpdater/Internal/HotUpdater-Bridging-Header.h +0 -1
  37. package/ios/HotUpdater/Internal/HotUpdater.mm +32 -67
  38. package/ios/HotUpdater/Internal/HotUpdaterImpl.swift +229 -73
  39. package/ios/HotUpdater/Internal/KeyValueStorageService.swift +71 -0
  40. package/ios/HotUpdater/Internal/NotificationExtension.swift +0 -2
  41. package/ios/HotUpdater/Internal/TarArchiveExtractor.swift +182 -311
  42. package/ios/HotUpdater/Internal/URLSessionDownloadService.swift +119 -71
  43. package/ios/HotUpdater/Internal/UpdateFailure.swift +390 -0
  44. package/ios/HotUpdater/Recovery/HotUpdaterRecovery.h +16 -0
  45. package/ios/HotUpdater/Recovery/HotUpdaterRecovery.mm +83 -0
  46. package/ios/HotUpdater/Recovery/HotUpdaterRecoveryHooks.mm +49 -0
  47. package/lib/commonjs/appReady.js +102 -0
  48. package/lib/commonjs/appReady.js.map +1 -0
  49. package/lib/commonjs/checkForUpdate.js +120 -68
  50. package/lib/commonjs/checkForUpdate.js.map +1 -1
  51. package/lib/commonjs/clientPlugin.js +13 -0
  52. package/lib/commonjs/clientPlugin.js.map +1 -0
  53. package/lib/commonjs/error.js +4 -13
  54. package/lib/commonjs/error.js.map +1 -1
  55. package/lib/commonjs/fetchJSON.js +16 -27
  56. package/lib/commonjs/fetchJSON.js.map +1 -1
  57. package/lib/commonjs/fetchUpdateResponse.js +60 -0
  58. package/lib/commonjs/fetchUpdateResponse.js.map +1 -0
  59. package/lib/commonjs/httpClient.js +63 -94
  60. package/lib/commonjs/httpClient.js.map +1 -1
  61. package/lib/commonjs/index.js +71 -18
  62. package/lib/commonjs/index.js.map +1 -1
  63. package/lib/commonjs/native.js +74 -60
  64. package/lib/commonjs/native.js.map +1 -1
  65. package/lib/commonjs/pluginHost.js +45 -0
  66. package/lib/commonjs/pluginHost.js.map +1 -0
  67. package/lib/commonjs/releaseCatalogCache.js +36 -87
  68. package/lib/commonjs/releaseCatalogCache.js.map +1 -1
  69. package/lib/commonjs/sdkVersion.js +1 -1
  70. package/lib/commonjs/sdkVersion.js.map +1 -1
  71. package/lib/commonjs/specs/NativeHotUpdater.js.map +1 -1
  72. package/lib/commonjs/store.js +3 -10
  73. package/lib/commonjs/store.js.map +1 -1
  74. package/lib/commonjs/updateError.js +145 -0
  75. package/lib/commonjs/updateError.js.map +1 -0
  76. package/lib/commonjs/wrap.js +43 -26
  77. package/lib/commonjs/wrap.js.map +1 -1
  78. package/lib/module/appReady.js +95 -0
  79. package/lib/module/appReady.js.map +1 -0
  80. package/lib/module/checkForUpdate.js +113 -63
  81. package/lib/module/checkForUpdate.js.map +1 -1
  82. package/lib/module/clientPlugin.js +4 -0
  83. package/lib/module/clientPlugin.js.map +1 -0
  84. package/lib/module/error.js +4 -13
  85. package/lib/module/error.js.map +1 -1
  86. package/lib/module/fetchJSON.js +14 -26
  87. package/lib/module/fetchJSON.js.map +1 -1
  88. package/lib/module/fetchUpdateResponse.js +55 -0
  89. package/lib/module/fetchUpdateResponse.js.map +1 -0
  90. package/lib/module/httpClient.js +62 -93
  91. package/lib/module/httpClient.js.map +1 -1
  92. package/lib/module/index.js +58 -20
  93. package/lib/module/index.js.map +1 -1
  94. package/lib/module/native.js +67 -53
  95. package/lib/module/native.js.map +1 -1
  96. package/lib/module/pluginHost.js +36 -0
  97. package/lib/module/pluginHost.js.map +1 -0
  98. package/lib/module/releaseCatalogCache.js +32 -82
  99. package/lib/module/releaseCatalogCache.js.map +1 -1
  100. package/lib/module/sdkVersion.js +1 -1
  101. package/lib/module/sdkVersion.js.map +1 -1
  102. package/lib/module/specs/NativeHotUpdater.js.map +1 -1
  103. package/lib/module/store.js +3 -10
  104. package/lib/module/store.js.map +1 -1
  105. package/lib/module/updateError.js +139 -0
  106. package/lib/module/updateError.js.map +1 -0
  107. package/lib/module/wrap.js +43 -26
  108. package/lib/module/wrap.js.map +1 -1
  109. package/lib/typescript/commonjs/appReady.d.ts +21 -0
  110. package/lib/typescript/commonjs/appReady.d.ts.map +1 -0
  111. package/lib/typescript/commonjs/checkForUpdate.d.ts +16 -4
  112. package/lib/typescript/commonjs/checkForUpdate.d.ts.map +1 -1
  113. package/lib/typescript/commonjs/clientPlugin.d.ts +2 -0
  114. package/lib/typescript/commonjs/clientPlugin.d.ts.map +1 -0
  115. package/lib/typescript/commonjs/error.d.ts +4 -13
  116. package/lib/typescript/commonjs/error.d.ts.map +1 -1
  117. package/lib/typescript/commonjs/fetchJSON.d.ts +5 -5
  118. package/lib/typescript/commonjs/fetchJSON.d.ts.map +1 -1
  119. package/lib/typescript/commonjs/fetchUpdateResponse.d.ts +14 -0
  120. package/lib/typescript/commonjs/fetchUpdateResponse.d.ts.map +1 -0
  121. package/lib/typescript/commonjs/httpClient.d.ts +4 -33
  122. package/lib/typescript/commonjs/httpClient.d.ts.map +1 -1
  123. package/lib/typescript/commonjs/index.d.ts +4 -8
  124. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  125. package/lib/typescript/commonjs/native.d.ts +29 -22
  126. package/lib/typescript/commonjs/native.d.ts.map +1 -1
  127. package/lib/typescript/commonjs/pluginHost.d.ts +4 -0
  128. package/lib/typescript/commonjs/pluginHost.d.ts.map +1 -0
  129. package/lib/typescript/commonjs/releaseCatalogCache.d.ts +8 -14
  130. package/lib/typescript/commonjs/releaseCatalogCache.d.ts.map +1 -1
  131. package/lib/typescript/commonjs/sdkVersion.d.ts +1 -1
  132. package/lib/typescript/commonjs/sdkVersion.d.ts.map +1 -1
  133. package/lib/typescript/commonjs/specs/NativeHotUpdater.d.ts +35 -47
  134. package/lib/typescript/commonjs/specs/NativeHotUpdater.d.ts.map +1 -1
  135. package/lib/typescript/commonjs/store.d.ts +1 -3
  136. package/lib/typescript/commonjs/store.d.ts.map +1 -1
  137. package/lib/typescript/commonjs/types.d.ts +1 -1
  138. package/lib/typescript/commonjs/types.d.ts.map +1 -1
  139. package/lib/typescript/commonjs/updateError.d.ts +26 -0
  140. package/lib/typescript/commonjs/updateError.d.ts.map +1 -0
  141. package/lib/typescript/commonjs/wrap.d.ts.map +1 -1
  142. package/lib/typescript/commonjs/wrap.types.d.ts +6 -7
  143. package/lib/typescript/commonjs/wrap.types.d.ts.map +1 -1
  144. package/lib/typescript/module/appReady.d.ts +21 -0
  145. package/lib/typescript/module/appReady.d.ts.map +1 -0
  146. package/lib/typescript/module/checkForUpdate.d.ts +16 -4
  147. package/lib/typescript/module/checkForUpdate.d.ts.map +1 -1
  148. package/lib/typescript/module/clientPlugin.d.ts +2 -0
  149. package/lib/typescript/module/clientPlugin.d.ts.map +1 -0
  150. package/lib/typescript/module/error.d.ts +4 -13
  151. package/lib/typescript/module/error.d.ts.map +1 -1
  152. package/lib/typescript/module/fetchJSON.d.ts +5 -5
  153. package/lib/typescript/module/fetchJSON.d.ts.map +1 -1
  154. package/lib/typescript/module/fetchUpdateResponse.d.ts +14 -0
  155. package/lib/typescript/module/fetchUpdateResponse.d.ts.map +1 -0
  156. package/lib/typescript/module/httpClient.d.ts +4 -33
  157. package/lib/typescript/module/httpClient.d.ts.map +1 -1
  158. package/lib/typescript/module/index.d.ts +4 -8
  159. package/lib/typescript/module/index.d.ts.map +1 -1
  160. package/lib/typescript/module/native.d.ts +29 -22
  161. package/lib/typescript/module/native.d.ts.map +1 -1
  162. package/lib/typescript/module/pluginHost.d.ts +4 -0
  163. package/lib/typescript/module/pluginHost.d.ts.map +1 -0
  164. package/lib/typescript/module/releaseCatalogCache.d.ts +8 -14
  165. package/lib/typescript/module/releaseCatalogCache.d.ts.map +1 -1
  166. package/lib/typescript/module/sdkVersion.d.ts +1 -1
  167. package/lib/typescript/module/sdkVersion.d.ts.map +1 -1
  168. package/lib/typescript/module/specs/NativeHotUpdater.d.ts +35 -47
  169. package/lib/typescript/module/specs/NativeHotUpdater.d.ts.map +1 -1
  170. package/lib/typescript/module/store.d.ts +1 -3
  171. package/lib/typescript/module/store.d.ts.map +1 -1
  172. package/lib/typescript/module/types.d.ts +1 -1
  173. package/lib/typescript/module/types.d.ts.map +1 -1
  174. package/lib/typescript/module/updateError.d.ts +26 -0
  175. package/lib/typescript/module/updateError.d.ts.map +1 -0
  176. package/lib/typescript/module/wrap.d.ts.map +1 -1
  177. package/lib/typescript/module/wrap.types.d.ts +6 -7
  178. package/lib/typescript/module/wrap.types.d.ts.map +1 -1
  179. package/package.json +7 -4
  180. package/src/appReady.ts +141 -0
  181. package/src/checkForUpdate.ts +145 -86
  182. package/src/clientPlugin.ts +18 -0
  183. package/src/error.ts +4 -14
  184. package/src/fetchJSON.ts +14 -30
  185. package/src/fetchUpdateResponse.ts +60 -0
  186. package/src/httpClient.ts +88 -159
  187. package/src/index.ts +90 -24
  188. package/src/native.ts +98 -102
  189. package/src/pluginHost.ts +47 -0
  190. package/src/releaseCatalogCache.ts +43 -172
  191. package/src/sdkVersion.ts +1 -1
  192. package/src/specs/NativeHotUpdater.ts +34 -48
  193. package/src/store.ts +2 -23
  194. package/src/types.ts +1 -1
  195. package/src/updateError.ts +167 -0
  196. package/src/wrap.tsx +57 -26
  197. package/src/wrap.types.ts +6 -7
  198. package/android/src/main/java/com/hotupdater/DecompressService.kt +0 -89
  199. package/android/src/main/java/com/hotupdater/DecompressionStrategy.kt +0 -26
  200. package/android/src/main/java/com/hotupdater/TarBrDecompressionStrategy.kt +0 -117
  201. package/android/src/main/java/com/hotupdater/TarGzDecompressionStrategy.kt +0 -117
  202. package/android/src/main/java/com/hotupdater/ZipDecompressionStrategy.kt +0 -192
  203. package/android/src/test/java/com/hotupdater/BsdiffPatchTest.kt +0 -46
  204. package/android/src/test/java/com/hotupdater/BundleFileStorageServiceTest.kt +0 -799
  205. package/android/src/test/java/com/hotupdater/HotUpdaterImplTest.kt +0 -273
  206. package/android/src/test/java/com/hotupdater/NativeConfigUtilsTest.kt +0 -20
  207. package/android/src/test/java/com/hotupdater/OkHttpDownloadServiceTest.kt +0 -111
  208. package/android/src/test/java/com/hotupdater/RelativePathResolverTest.kt +0 -41
  209. package/android/src/test/java/com/hotupdater/ReleaseCatalogCacheServiceTest.kt +0 -118
  210. package/android/src/test/java/com/hotupdater/TarArchiveInputStreamTest.kt +0 -68
  211. package/ios/HotUpdater/Internal/ArchiveExtractionUtilities.swift +0 -178
  212. package/ios/HotUpdater/Internal/DecompressService.swift +0 -112
  213. package/ios/HotUpdater/Internal/DecompressionStrategy.swift +0 -22
  214. package/ios/HotUpdater/Internal/StreamingTarArchiveExtractor.swift +0 -370
  215. package/ios/HotUpdater/Internal/TarBrDecompressionStrategy.swift +0 -39
  216. package/ios/HotUpdater/Internal/TarGzDecompressionStrategy.swift +0 -59
  217. package/ios/HotUpdater/Internal/ZipArchiveExtractor.swift +0 -482
  218. package/ios/HotUpdater/Internal/ZipDecompressionStrategy.swift +0 -56
  219. package/lib/commonjs/catalogCacheNative.spec.js +0 -31
  220. package/lib/commonjs/catalogCacheNative.spec.js.map +0 -1
  221. package/lib/commonjs/checkForUpdate.releaseCatalog.spec.js +0 -616
  222. package/lib/commonjs/checkForUpdate.releaseCatalog.spec.js.map +0 -1
  223. package/lib/commonjs/httpClient.spec.js +0 -102
  224. package/lib/commonjs/httpClient.spec.js.map +0 -1
  225. package/lib/commonjs/index.spec.js +0 -302
  226. package/lib/commonjs/index.spec.js.map +0 -1
  227. package/lib/commonjs/iosInterop.spec.js +0 -18
  228. package/lib/commonjs/iosInterop.spec.js.map +0 -1
  229. package/lib/commonjs/native.spec.js +0 -883
  230. package/lib/commonjs/native.spec.js.map +0 -1
  231. package/lib/commonjs/notifyAppReadyInsights.boundary.spec.js +0 -218
  232. package/lib/commonjs/notifyAppReadyInsights.boundary.spec.js.map +0 -1
  233. package/lib/commonjs/notifyAppReadyInsights.js +0 -133
  234. package/lib/commonjs/notifyAppReadyInsights.js.map +0 -1
  235. package/lib/commonjs/notifyAppReadyInsights.spec.js +0 -246
  236. package/lib/commonjs/notifyAppReadyInsights.spec.js.map +0 -1
  237. package/lib/commonjs/notifyAppReadyInsights.test-utils.js +0 -24
  238. package/lib/commonjs/notifyAppReadyInsights.test-utils.js.map +0 -1
  239. package/lib/commonjs/notifyAppReadyInsights.transport.spec.js +0 -117
  240. package/lib/commonjs/notifyAppReadyInsights.transport.spec.js.map +0 -1
  241. package/lib/commonjs/releaseCatalogCache.spec.js +0 -195
  242. package/lib/commonjs/releaseCatalogCache.spec.js.map +0 -1
  243. package/lib/commonjs/releaseCatalogCacheNativeContract.spec.js +0 -64
  244. package/lib/commonjs/releaseCatalogCacheNativeContract.spec.js.map +0 -1
  245. package/lib/commonjs/store.notification.spec.js +0 -76
  246. package/lib/commonjs/store.notification.spec.js.map +0 -1
  247. package/lib/commonjs/store.spec.js +0 -316
  248. package/lib/commonjs/store.spec.js.map +0 -1
  249. package/lib/commonjs/wrap.spec.js +0 -329
  250. package/lib/commonjs/wrap.spec.js.map +0 -1
  251. package/lib/module/catalogCacheNative.spec.js +0 -31
  252. package/lib/module/catalogCacheNative.spec.js.map +0 -1
  253. package/lib/module/checkForUpdate.releaseCatalog.spec.js +0 -615
  254. package/lib/module/checkForUpdate.releaseCatalog.spec.js.map +0 -1
  255. package/lib/module/httpClient.spec.js +0 -102
  256. package/lib/module/httpClient.spec.js.map +0 -1
  257. package/lib/module/index.spec.js +0 -301
  258. package/lib/module/index.spec.js.map +0 -1
  259. package/lib/module/iosInterop.spec.js +0 -18
  260. package/lib/module/iosInterop.spec.js.map +0 -1
  261. package/lib/module/native.spec.js +0 -882
  262. package/lib/module/native.spec.js.map +0 -1
  263. package/lib/module/notifyAppReadyInsights.boundary.spec.js +0 -217
  264. package/lib/module/notifyAppReadyInsights.boundary.spec.js.map +0 -1
  265. package/lib/module/notifyAppReadyInsights.js +0 -128
  266. package/lib/module/notifyAppReadyInsights.js.map +0 -1
  267. package/lib/module/notifyAppReadyInsights.spec.js +0 -245
  268. package/lib/module/notifyAppReadyInsights.spec.js.map +0 -1
  269. package/lib/module/notifyAppReadyInsights.test-utils.js +0 -18
  270. package/lib/module/notifyAppReadyInsights.test-utils.js.map +0 -1
  271. package/lib/module/notifyAppReadyInsights.transport.spec.js +0 -116
  272. package/lib/module/notifyAppReadyInsights.transport.spec.js.map +0 -1
  273. package/lib/module/releaseCatalogCache.spec.js +0 -195
  274. package/lib/module/releaseCatalogCache.spec.js.map +0 -1
  275. package/lib/module/releaseCatalogCacheNativeContract.spec.js +0 -64
  276. package/lib/module/releaseCatalogCacheNativeContract.spec.js.map +0 -1
  277. package/lib/module/store.notification.spec.js +0 -77
  278. package/lib/module/store.notification.spec.js.map +0 -1
  279. package/lib/module/store.spec.js +0 -315
  280. package/lib/module/store.spec.js.map +0 -1
  281. package/lib/module/wrap.spec.js +0 -330
  282. package/lib/module/wrap.spec.js.map +0 -1
  283. package/lib/typescript/commonjs/notifyAppReadyInsights.d.ts +0 -13
  284. package/lib/typescript/commonjs/notifyAppReadyInsights.d.ts.map +0 -1
  285. package/lib/typescript/commonjs/notifyAppReadyInsights.test-utils.d.ts +0 -8
  286. package/lib/typescript/commonjs/notifyAppReadyInsights.test-utils.d.ts.map +0 -1
  287. package/lib/typescript/module/notifyAppReadyInsights.d.ts +0 -13
  288. package/lib/typescript/module/notifyAppReadyInsights.d.ts.map +0 -1
  289. package/lib/typescript/module/notifyAppReadyInsights.test-utils.d.ts +0 -8
  290. package/lib/typescript/module/notifyAppReadyInsights.test-utils.d.ts.map +0 -1
  291. package/src/catalogCacheNative.spec.ts +0 -63
  292. package/src/checkForUpdate.releaseCatalog.spec.ts +0 -612
  293. package/src/httpClient.spec.ts +0 -132
  294. package/src/index.spec.ts +0 -337
  295. package/src/iosInterop.spec.ts +0 -30
  296. package/src/native.spec.ts +0 -945
  297. package/src/notifyAppReadyInsights.boundary.spec.ts +0 -234
  298. package/src/notifyAppReadyInsights.spec.ts +0 -243
  299. package/src/notifyAppReadyInsights.test-utils.ts +0 -31
  300. package/src/notifyAppReadyInsights.transport.spec.ts +0 -130
  301. package/src/notifyAppReadyInsights.ts +0 -194
  302. package/src/releaseCatalogCache.spec.ts +0 -282
  303. package/src/releaseCatalogCacheNativeContract.spec.ts +0 -80
  304. package/src/store.notification.spec.ts +0 -92
  305. package/src/store.spec.ts +0 -372
  306. package/src/wrap.spec.ts +0 -406
@@ -1,132 +0,0 @@
1
- import type { ArtifactInfo, ReleaseCatalog } from "@hot-updater/core";
2
- import { beforeEach, describe, expect, it, vi } from "vitest";
3
-
4
- import { createHttpClient } from "./httpClient";
5
-
6
- const mocks = vi.hoisted(() => {
7
- Reflect.set(globalThis, "HotUpdater", {
8
- SDK_VERSION: "test-sdk-version",
9
- });
10
- return {
11
- fetchCatalog: vi.fn(),
12
- fetchJSON: vi.fn(),
13
- };
14
- });
15
-
16
- vi.mock("./releaseCatalogCache", () => ({
17
- fetchReleaseCatalogWithCache: mocks.fetchCatalog,
18
- }));
19
-
20
- vi.mock("./fetchJSON", () => ({
21
- fetchJSON: mocks.fetchJSON,
22
- }));
23
-
24
- const artifact: ArtifactInfo = {
25
- fileHash: "bundle-hash",
26
- fileUrl: "/storage/bundle.zip",
27
- };
28
-
29
- const catalog: ReleaseCatalog = {
30
- catalogId: "server-owned-project",
31
- catalogHash: `sha256:${"a".repeat(64)}`,
32
- fallbackPolicy: "BUILTIN_IF_ACTIVE_INELIGIBLE",
33
- generation: 1,
34
- releases: [],
35
- schemaVersion: 1,
36
- scopeKey: "v1:app-version:server-owned-project:ios:cHJvZHVjdGlvbg",
37
- };
38
-
39
- describe("private HotUpdater HTTP client", () => {
40
- beforeEach(() => {
41
- vi.clearAllMocks();
42
- mocks.fetchCatalog.mockResolvedValue(catalog);
43
- mocks.fetchJSON.mockResolvedValue(artifact);
44
- });
45
-
46
- it("fetches a catalog without putting its internal identity in the route", async () => {
47
- const session = await createHttpClient(
48
- "https://updates.example.com/hot-updater/",
49
- ).createSession();
50
-
51
- await expect(
52
- session.fetchReleaseCatalog({
53
- appVersion: "1.2.0",
54
- channel: "production",
55
- fingerprintHash: null,
56
- platform: "ios",
57
- updateStrategy: "appVersion",
58
- }),
59
- ).resolves.toBe(catalog);
60
-
61
- expect(mocks.fetchCatalog).toHaveBeenCalledWith({
62
- baseURL: "https://updates.example.com/hot-updater",
63
- expectedScope: {
64
- channelKey: "cHJvZHVjdGlvbg",
65
- platform: "ios",
66
- strategy: "APP_VERSION",
67
- },
68
- requestHeaders: undefined,
69
- requestTimeout: undefined,
70
- url: "https://updates.example.com/hot-updater/release-catalogs/app-version/ios/cHJvZHVjdGlvbg/1.2.0",
71
- });
72
- });
73
-
74
- it("resolves a functional baseURL once per session and captures it for a deferred artifact", async () => {
75
- const resolveBaseURL = vi
76
- .fn()
77
- .mockResolvedValueOnce("https://first.example.com/hot-updater")
78
- .mockResolvedValueOnce("https://second.example.com/hot-updater");
79
- const client = createHttpClient(resolveBaseURL);
80
- const firstSession = await client.createSession();
81
-
82
- await firstSession.fetchReleaseCatalog({
83
- appVersion: "1.2.0",
84
- channel: "production",
85
- fingerprintHash: null,
86
- platform: "ios",
87
- updateStrategy: "appVersion",
88
- });
89
- await expect(
90
- firstSession.resolveArtifact({
91
- currentBundleId: "current",
92
- targetBundleId: "target",
93
- }),
94
- ).resolves.toEqual({
95
- ...artifact,
96
- fileUrl: "https://first.example.com/hot-updater/storage/bundle.zip",
97
- });
98
-
99
- expect(resolveBaseURL).toHaveBeenCalledOnce();
100
- expect(mocks.fetchJSON).toHaveBeenCalledWith({
101
- requestHeaders: undefined,
102
- requestTimeout: undefined,
103
- url: "https://first.example.com/hot-updater/artifacts/target/from/current",
104
- });
105
-
106
- await client.createSession();
107
- expect(resolveBaseURL).toHaveBeenCalledTimes(2);
108
- });
109
-
110
- it("rejects non-storage relative artifact URLs", async () => {
111
- mocks.fetchJSON.mockResolvedValue({
112
- ...artifact,
113
- fileUrl: "/private/bundle.zip",
114
- });
115
- const session = await createHttpClient(
116
- "https://updates.example.com",
117
- ).createSession();
118
-
119
- await expect(
120
- session.resolveArtifact({
121
- currentBundleId: "current",
122
- targetBundleId: "target",
123
- }),
124
- ).rejects.toThrow("client-relative storage paths");
125
- });
126
-
127
- it("requires a functional baseURL to resolve to a non-empty string", async () => {
128
- await expect(createHttpClient(() => "").createSession()).rejects.toThrow(
129
- "baseURL function must return a non-empty string",
130
- );
131
- });
132
- });
package/src/index.spec.ts DELETED
@@ -1,337 +0,0 @@
1
- import { beforeEach, describe, expect, it, vi } from "vitest";
2
-
3
- import type { HotUpdaterInitOptions, HotUpdaterOptions } from "./wrap";
4
-
5
- const mocks = vi.hoisted(() => {
6
- (
7
- globalThis as typeof globalThis & {
8
- HotUpdater: { SDK_VERSION: string };
9
- }
10
- ).HotUpdater = { SDK_VERSION: "test-sdk-version" };
11
-
12
- return {
13
- addListener: vi.fn(() => () => {}),
14
- checkForUpdate: vi.fn(async () => null),
15
- clearCrashHistory: vi.fn(() => true),
16
- createHttpClient: vi.fn((baseURL: unknown) => ({ baseURL })),
17
- getActiveUpdateState: vi.fn(() => ({
18
- activeSelection: null,
19
- highestSeenCatalogs: {},
20
- stableSelection: null,
21
- verificationPending: false,
22
- })),
23
- getAppVersion: vi.fn(() => "1.0.0"),
24
- getBaseURL: vi.fn(() => null),
25
- getUpdateId: vi.fn(() => "release-id"),
26
- getChannel: vi.fn(() => "production"),
27
- getCohort: vi.fn(() => "123"),
28
- getCrashHistory: vi.fn(() => []),
29
- getDefaultChannel: vi.fn(() => "production"),
30
- getFingerprintHash: vi.fn(() => null),
31
- getInstallId: vi.fn(() => "install-id"),
32
- getManifest: vi.fn(() => null),
33
- getMinBundleId: vi.fn(() => "min-bundle-id"),
34
- init: vi.fn(),
35
- isChannelSwitched: vi.fn(() => false),
36
- notifyAppReady: vi.fn(() => ({ status: "UNCHANGED" as const })),
37
- reload: vi.fn(),
38
- resetChannel: vi.fn(),
39
- setCohort: vi.fn(),
40
- setReloadBehavior: vi.fn(),
41
- setUser: vi.fn(),
42
- updateBundle: vi.fn(),
43
- wrap: vi.fn((Component: unknown) => Component),
44
- };
45
- });
46
-
47
- vi.mock("./httpClient", () => ({
48
- createHttpClient: mocks.createHttpClient,
49
- }));
50
-
51
- vi.mock("./checkForUpdate", () => ({
52
- checkForUpdate: mocks.checkForUpdate,
53
- }));
54
-
55
- vi.mock("./native", () => ({
56
- addListener: mocks.addListener,
57
- clearCrashHistory: mocks.clearCrashHistory,
58
- getPublicActiveUpdateState: mocks.getActiveUpdateState,
59
- getAppVersion: mocks.getAppVersion,
60
- getBaseURL: mocks.getBaseURL,
61
- getUpdateId: mocks.getUpdateId,
62
- getChannel: mocks.getChannel,
63
- getCohort: mocks.getCohort,
64
- getCrashHistory: mocks.getCrashHistory,
65
- getDefaultChannel: mocks.getDefaultChannel,
66
- getFingerprintHash: mocks.getFingerprintHash,
67
- getInstallId: mocks.getInstallId,
68
- getManifest: mocks.getManifest,
69
- getMinBundleId: mocks.getMinBundleId,
70
- isChannelSwitched: mocks.isChannelSwitched,
71
- notifyAppReady: mocks.notifyAppReady,
72
- reload: mocks.reload,
73
- resetChannel: mocks.resetChannel,
74
- setCohort: mocks.setCohort,
75
- setReloadBehavior: mocks.setReloadBehavior,
76
- setUser: mocks.setUser,
77
- updateBundle: mocks.updateBundle,
78
- }));
79
-
80
- vi.mock("./wrap", () => ({
81
- init: mocks.init,
82
- wrap: mocks.wrap,
83
- }));
84
-
85
- const importHotUpdater = async () => (await import("./index")).HotUpdater;
86
-
87
- describe("HotUpdater client initialization", () => {
88
- beforeEach(() => {
89
- vi.resetModules();
90
- vi.clearAllMocks();
91
- mocks.createHttpClient.mockImplementation((baseURL: unknown) => ({
92
- baseURL,
93
- }));
94
- mocks.checkForUpdate.mockResolvedValue(null);
95
- mocks.wrap.mockImplementation((Component: unknown) => Component);
96
- });
97
-
98
- it("exposes the console ID through the existing getter only", async () => {
99
- const HotUpdater = await importHotUpdater();
100
-
101
- expect(HotUpdater.getBundleId()).toBe("release-id");
102
- expect(HotUpdater).not.toHaveProperty("getReleaseId");
103
- expect(HotUpdater).not.toHaveProperty("getUpdateId");
104
- });
105
-
106
- it("initializes a private HTTP client from the required baseURL", async () => {
107
- const client = { createSession: vi.fn() };
108
- mocks.createHttpClient.mockReturnValue(client as never);
109
- const HotUpdater = await importHotUpdater();
110
-
111
- HotUpdater.init({
112
- insights: true,
113
- baseURL: "https://updates.example.com",
114
- requestHeaders: { Authorization: "Bearer token" },
115
- requestTimeout: 1000,
116
- });
117
-
118
- expect(mocks.createHttpClient).toHaveBeenCalledWith(
119
- "https://updates.example.com",
120
- );
121
- expect(mocks.init).toHaveBeenCalledWith({
122
- insights: true,
123
- client,
124
- requestHeaders: { Authorization: "Bearer token" },
125
- requestTimeout: 1000,
126
- });
127
- });
128
-
129
- it("accepts a functional baseURL without resolving it during init", async () => {
130
- const resolveBaseURL = vi.fn(() => "https://updates.example.com");
131
- const HotUpdater = await importHotUpdater();
132
-
133
- HotUpdater.init({ baseURL: resolveBaseURL });
134
-
135
- expect(mocks.createHttpClient).toHaveBeenCalledWith(resolveBaseURL);
136
- expect(resolveBaseURL).not.toHaveBeenCalled();
137
- });
138
-
139
- it("enables insights by default for init and wrap", async () => {
140
- const HotUpdater = await importHotUpdater();
141
-
142
- HotUpdater.init({ baseURL: "https://updates.example.com" });
143
- HotUpdater.wrap({
144
- baseURL: "https://updates.example.com",
145
- updateStrategy: "appVersion",
146
- });
147
-
148
- expect(mocks.init).toHaveBeenCalledWith(
149
- expect.objectContaining({ insights: true }),
150
- );
151
- expect(mocks.wrap).toHaveBeenCalledWith(
152
- expect.objectContaining({ insights: true }),
153
- );
154
- });
155
-
156
- it("preserves an explicit insights opt-out", async () => {
157
- const HotUpdater = await importHotUpdater();
158
-
159
- HotUpdater.init({
160
- baseURL: "https://updates.example.com",
161
- insights: false,
162
- });
163
- HotUpdater.wrap({
164
- baseURL: "https://updates.example.com",
165
- insights: false,
166
- updateStrategy: "appVersion",
167
- });
168
-
169
- expect(mocks.init).toHaveBeenCalledWith(
170
- expect.objectContaining({ insights: false }),
171
- );
172
- expect(mocks.wrap).toHaveBeenCalledWith(
173
- expect.objectContaining({ insights: false }),
174
- );
175
- });
176
-
177
- it("requires baseURL and rejects the removed resolver shape", async () => {
178
- const HotUpdater = await importHotUpdater();
179
-
180
- expect(() => HotUpdater.init({} as never)).toThrow(
181
- "baseURL must be provided",
182
- );
183
- expect(() => HotUpdater.init({ resolver: {} } as never)).toThrow(
184
- "baseURL must be provided",
185
- );
186
- expect(mocks.init).not.toHaveBeenCalled();
187
- });
188
-
189
- it("types init and wrap with baseURL but no resolver or catalogId", () => {
190
- const initOptions = {
191
- baseURL: "https://updates.example.com",
192
- } satisfies HotUpdaterInitOptions;
193
- const wrapOptions = {
194
- baseURL: async () => "https://updates.example.com",
195
- updateStrategy: "appVersion",
196
- } satisfies HotUpdaterOptions;
197
-
198
- const assertRemovedInputsStayRejected = () => {
199
- // @ts-expect-error baseURL is required
200
- const missingBaseURL: HotUpdaterInitOptions = {};
201
- // @ts-expect-error resolver is no longer a public input
202
- const customResolver: HotUpdaterInitOptions = { resolver: {} };
203
- const clientCatalog: HotUpdaterInitOptions = {
204
- // @ts-expect-error catalogId is internal protocol metadata
205
- catalogId: "project-a",
206
- baseURL: "https://updates.example.com",
207
- };
208
- void missingBaseURL;
209
- void customResolver;
210
- void clientCatalog;
211
- };
212
-
213
- expect(assertRemovedInputsStayRejected).toBeTypeOf("function");
214
- expect(initOptions.baseURL).toBe("https://updates.example.com");
215
- expect(wrapOptions.updateStrategy).toBe("appVersion");
216
- });
217
-
218
- it("merges settings and carries the insights gate to checks", async () => {
219
- const client = { createSession: vi.fn() };
220
- mocks.createHttpClient.mockReturnValue(client as never);
221
- const checkOnError = vi.fn();
222
- const HotUpdater = await importHotUpdater();
223
- HotUpdater.init({
224
- insights: true,
225
- baseURL: "https://updates.example.com",
226
- requestHeaders: { Authorization: "Bearer token" },
227
- requestTimeout: 1000,
228
- });
229
-
230
- await HotUpdater.checkForUpdate({
231
- onError: checkOnError,
232
- requestHeaders: { "X-Runtime": "secondary" },
233
- updateStrategy: "appVersion",
234
- });
235
-
236
- expect(mocks.checkForUpdate).toHaveBeenCalledWith({
237
- insights: true,
238
- client,
239
- onError: checkOnError,
240
- requestHeaders: {
241
- Authorization: "Bearer token",
242
- "X-Runtime": "secondary",
243
- },
244
- requestTimeout: 1000,
245
- updateStrategy: "appVersion",
246
- });
247
- });
248
-
249
- it("normalizes wrap with the same private client contract", async () => {
250
- const client = { createSession: vi.fn() };
251
- mocks.createHttpClient.mockReturnValue(client as never);
252
- const HotUpdater = await importHotUpdater();
253
-
254
- HotUpdater.wrap({
255
- insights: true,
256
- baseURL: "https://updates.example.com",
257
- updateStrategy: "appVersion",
258
- });
259
-
260
- expect(mocks.wrap).toHaveBeenCalledWith({
261
- insights: true,
262
- client,
263
- updateStrategy: "appVersion",
264
- });
265
- });
266
-
267
- it.each([
268
- ["init", "wrap"],
269
- ["wrap", "init"],
270
- ] as const)(
271
- "reports %s and %s mixed usage exactly once",
272
- async (first, second) => {
273
- const consoleError = vi
274
- .spyOn(console, "error")
275
- .mockImplementation(() => undefined);
276
- const HotUpdater = await importHotUpdater();
277
- const configure = (api: "init" | "wrap") => {
278
- if (api === "init") {
279
- HotUpdater.init({ baseURL: "https://updates.example.com" });
280
- return;
281
- }
282
- HotUpdater.wrap({
283
- baseURL: "https://updates.example.com",
284
- updateStrategy: "appVersion",
285
- });
286
- };
287
-
288
- configure(first);
289
- configure(second);
290
- configure(second);
291
-
292
- expect(consoleError).toHaveBeenCalledOnce();
293
- expect(consoleError).toHaveBeenCalledWith(
294
- expect.stringContaining(
295
- "HotUpdater.init() and HotUpdater.wrap() must not be used together",
296
- ),
297
- );
298
- expect(consoleError).toHaveBeenCalledWith(
299
- expect.stringContaining(
300
- "use HotUpdater.init() with HotUpdater.checkForUpdate()",
301
- ),
302
- );
303
- consoleError.mockRestore();
304
- },
305
- );
306
-
307
- it("rejects removed manual wrap options", async () => {
308
- const HotUpdater = await importHotUpdater();
309
-
310
- expect(() =>
311
- HotUpdater.wrap({
312
- baseURL: "https://updates.example.com",
313
- updateMode: "manual",
314
- } as never),
315
- ).toThrow('HotUpdater.wrap({ updateMode: "manual" }) was removed');
316
- });
317
-
318
- it("requires initialization before manual update APIs", async () => {
319
- const HotUpdater = await importHotUpdater();
320
-
321
- expect(() =>
322
- HotUpdater.checkForUpdate({ updateStrategy: "appVersion" }),
323
- ).toThrow("requires HotUpdater.wrap() or HotUpdater.init() to be used");
324
- });
325
-
326
- it("preserves native identity and user APIs", async () => {
327
- const HotUpdater = await importHotUpdater();
328
-
329
- expect(HotUpdater.getInstallId()).toBe("install-id");
330
- expect(HotUpdater.getMinBundleId()).toBe("min-bundle-id");
331
- HotUpdater.setUser({ userId: "user-123", username: "alice" });
332
- expect(mocks.setUser).toHaveBeenCalledWith({
333
- userId: "user-123",
334
- username: "alice",
335
- });
336
- });
337
- });
@@ -1,30 +0,0 @@
1
- import { readFileSync } from "node:fs";
2
- import { resolve } from "node:path";
3
-
4
- import { describe, expect, it } from "vitest";
5
-
6
- const iosInternalDirectory = resolve(
7
- import.meta.dirname,
8
- "../ios/HotUpdater/Internal",
9
- );
10
-
11
- const readIOSSource = (filename: string) =>
12
- readFileSync(resolve(iosInternalDirectory, filename), "utf8");
13
-
14
- describe("iOS Objective-C interoperability", () => {
15
- it("does not call an autoreleased NSString through raw Swift ABI", () => {
16
- const implementation = readIOSSource("HotUpdaterImpl.swift");
17
- const objectiveCImplementation = readIOSSource("HotUpdater.mm");
18
-
19
- expect(implementation).not.toContain(
20
- '@_silgen_name("HotUpdaterGetMinBundleId")',
21
- );
22
- expect(implementation).toContain(
23
- '@_silgen_name("HotUpdaterCopyMinBundleId")',
24
- );
25
- expect(implementation).toContain(".takeRetainedValue() as String");
26
- expect(objectiveCImplementation).toContain(
27
- "return (__bridge_retained void *)HotUpdaterGetMinBundleId();",
28
- );
29
- });
30
- });