@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.
Files changed (239) hide show
  1. package/android/src/main/java/com/hotupdater/BundleFileStorageService.kt +357 -6
  2. package/android/src/main/java/com/hotupdater/BundleMetadata.kt +268 -34
  3. package/android/src/main/java/com/hotupdater/HotUpdaterImpl.kt +75 -9
  4. package/android/src/main/java/com/hotupdater/NativeConfigUtils.kt +2 -16
  5. package/android/src/main/java/com/hotupdater/ReleaseCatalogCacheService.kt +166 -0
  6. package/android/src/main/java/com/hotupdater/SignatureVerifier.kt +1 -2
  7. package/android/src/newarch/HotUpdater.kt +1 -1
  8. package/android/src/newarch/HotUpdaterModule.kt +116 -0
  9. package/android/src/oldarch/HotUpdater.kt +1 -1
  10. package/android/src/oldarch/HotUpdaterModule.kt +128 -0
  11. package/android/src/oldarch/HotUpdaterSpec.kt +38 -0
  12. package/android/src/test/java/com/hotupdater/BundleFileStorageServiceTest.kt +280 -2
  13. package/android/src/test/java/com/hotupdater/HotUpdaterImplTest.kt +57 -2
  14. package/android/src/test/java/com/hotupdater/ReleaseCatalogCacheServiceTest.kt +118 -0
  15. package/ios/HotUpdater/Internal/BundleFileStorageService.swift +491 -30
  16. package/ios/HotUpdater/Internal/BundleMetadata.swift +229 -6
  17. package/ios/HotUpdater/Internal/HotUpdater.mm +122 -0
  18. package/ios/HotUpdater/Internal/HotUpdaterImpl.swift +176 -7
  19. package/ios/HotUpdater/Internal/ReleaseCatalogCacheService.swift +213 -0
  20. package/lib/commonjs/catalogCacheNative.js +44 -0
  21. package/lib/commonjs/catalogCacheNative.js.map +1 -0
  22. package/lib/commonjs/catalogCacheNative.spec.js +31 -0
  23. package/lib/commonjs/catalogCacheNative.spec.js.map +1 -0
  24. package/lib/commonjs/checkForUpdate.js +231 -60
  25. package/lib/commonjs/checkForUpdate.js.map +1 -1
  26. package/lib/commonjs/checkForUpdate.releaseCatalog.spec.js +604 -0
  27. package/lib/commonjs/checkForUpdate.releaseCatalog.spec.js.map +1 -0
  28. package/lib/commonjs/error.js +8 -1
  29. package/lib/commonjs/error.js.map +1 -1
  30. package/lib/commonjs/{fetchUpdateInfo.js → fetchJSON.js} +11 -14
  31. package/lib/commonjs/fetchJSON.js.map +1 -0
  32. package/lib/commonjs/httpClient.js +153 -0
  33. package/lib/commonjs/httpClient.js.map +1 -0
  34. package/lib/commonjs/httpClient.spec.js +102 -0
  35. package/lib/commonjs/httpClient.spec.js.map +1 -0
  36. package/lib/commonjs/index.js +47 -70
  37. package/lib/commonjs/index.js.map +1 -1
  38. package/lib/commonjs/index.spec.js +115 -159
  39. package/lib/commonjs/index.spec.js.map +1 -1
  40. package/lib/commonjs/iosInterop.spec.js +18 -0
  41. package/lib/commonjs/iosInterop.spec.js.map +1 -0
  42. package/lib/commonjs/native.js +222 -53
  43. package/lib/commonjs/native.js.map +1 -1
  44. package/lib/commonjs/native.spec.js +226 -12
  45. package/lib/commonjs/native.spec.js.map +1 -1
  46. package/lib/commonjs/notifyAppReadyAnalytics.boundary.spec.js +218 -0
  47. package/lib/commonjs/notifyAppReadyAnalytics.boundary.spec.js.map +1 -0
  48. package/lib/commonjs/notifyAppReadyAnalytics.js +133 -0
  49. package/lib/commonjs/notifyAppReadyAnalytics.js.map +1 -0
  50. package/lib/commonjs/notifyAppReadyAnalytics.spec.js +246 -0
  51. package/lib/commonjs/notifyAppReadyAnalytics.spec.js.map +1 -0
  52. package/lib/commonjs/notifyAppReadyAnalytics.test-utils.js +24 -0
  53. package/lib/commonjs/notifyAppReadyAnalytics.test-utils.js.map +1 -0
  54. package/lib/commonjs/notifyAppReadyAnalytics.transport.spec.js +117 -0
  55. package/lib/commonjs/notifyAppReadyAnalytics.transport.spec.js.map +1 -0
  56. package/lib/commonjs/releaseCatalogCache.js +179 -0
  57. package/lib/commonjs/releaseCatalogCache.js.map +1 -0
  58. package/lib/commonjs/releaseCatalogCache.spec.js +195 -0
  59. package/lib/commonjs/releaseCatalogCache.spec.js.map +1 -0
  60. package/lib/commonjs/releaseCatalogCacheNativeContract.spec.js +64 -0
  61. package/lib/commonjs/releaseCatalogCacheNativeContract.spec.js.map +1 -0
  62. package/lib/commonjs/sdkVersion.js +1 -1
  63. package/lib/commonjs/sdkVersion.js.map +1 -1
  64. package/lib/commonjs/specs/NativeHotUpdater.js.map +1 -1
  65. package/lib/commonjs/types.js +0 -12
  66. package/lib/commonjs/types.js.map +1 -1
  67. package/lib/commonjs/wrap.js +7 -82
  68. package/lib/commonjs/wrap.js.map +1 -1
  69. package/lib/commonjs/wrap.spec.js +203 -56
  70. package/lib/commonjs/wrap.spec.js.map +1 -1
  71. package/lib/commonjs/wrap.types.js +6 -0
  72. package/lib/commonjs/wrap.types.js.map +1 -0
  73. package/lib/module/catalogCacheNative.js +36 -0
  74. package/lib/module/catalogCacheNative.js.map +1 -0
  75. package/lib/module/catalogCacheNative.spec.js +31 -0
  76. package/lib/module/catalogCacheNative.spec.js.map +1 -0
  77. package/lib/module/checkForUpdate.js +233 -62
  78. package/lib/module/checkForUpdate.js.map +1 -1
  79. package/lib/module/checkForUpdate.releaseCatalog.spec.js +603 -0
  80. package/lib/module/checkForUpdate.releaseCatalog.spec.js.map +1 -0
  81. package/lib/module/error.js +6 -0
  82. package/lib/module/error.js.map +1 -1
  83. package/lib/module/{fetchUpdateInfo.js → fetchJSON.js} +9 -12
  84. package/lib/module/fetchJSON.js.map +1 -0
  85. package/lib/module/httpClient.js +148 -0
  86. package/lib/module/httpClient.js.map +1 -0
  87. package/lib/module/httpClient.spec.js +102 -0
  88. package/lib/module/httpClient.spec.js.map +1 -0
  89. package/lib/module/index.js +48 -65
  90. package/lib/module/index.js.map +1 -1
  91. package/lib/module/index.spec.js +115 -159
  92. package/lib/module/index.spec.js.map +1 -1
  93. package/lib/module/iosInterop.spec.js +18 -0
  94. package/lib/module/iosInterop.spec.js.map +1 -0
  95. package/lib/module/native.js +206 -49
  96. package/lib/module/native.js.map +1 -1
  97. package/lib/module/native.spec.js +226 -12
  98. package/lib/module/native.spec.js.map +1 -1
  99. package/lib/module/notifyAppReadyAnalytics.boundary.spec.js +217 -0
  100. package/lib/module/notifyAppReadyAnalytics.boundary.spec.js.map +1 -0
  101. package/lib/module/notifyAppReadyAnalytics.js +128 -0
  102. package/lib/module/notifyAppReadyAnalytics.js.map +1 -0
  103. package/lib/module/notifyAppReadyAnalytics.spec.js +245 -0
  104. package/lib/module/notifyAppReadyAnalytics.spec.js.map +1 -0
  105. package/lib/module/notifyAppReadyAnalytics.test-utils.js +18 -0
  106. package/lib/module/notifyAppReadyAnalytics.test-utils.js.map +1 -0
  107. package/lib/module/notifyAppReadyAnalytics.transport.spec.js +116 -0
  108. package/lib/module/notifyAppReadyAnalytics.transport.spec.js.map +1 -0
  109. package/lib/module/releaseCatalogCache.js +171 -0
  110. package/lib/module/releaseCatalogCache.js.map +1 -0
  111. package/lib/module/releaseCatalogCache.spec.js +195 -0
  112. package/lib/module/releaseCatalogCache.spec.js.map +1 -0
  113. package/lib/module/releaseCatalogCacheNativeContract.spec.js +64 -0
  114. package/lib/module/releaseCatalogCacheNativeContract.spec.js.map +1 -0
  115. package/lib/module/sdkVersion.js +1 -1
  116. package/lib/module/sdkVersion.js.map +1 -1
  117. package/lib/module/specs/NativeHotUpdater.js.map +1 -1
  118. package/lib/module/types.js +0 -12
  119. package/lib/module/types.js.map +1 -1
  120. package/lib/module/wrap.js +6 -81
  121. package/lib/module/wrap.js.map +1 -1
  122. package/lib/module/wrap.spec.js +203 -56
  123. package/lib/module/wrap.spec.js.map +1 -1
  124. package/lib/module/wrap.types.js +4 -0
  125. package/lib/module/wrap.types.js.map +1 -0
  126. package/lib/typescript/commonjs/catalogCacheNative.d.ts +4 -0
  127. package/lib/typescript/commonjs/catalogCacheNative.d.ts.map +1 -0
  128. package/lib/typescript/commonjs/checkForUpdate.d.ts +14 -4
  129. package/lib/typescript/commonjs/checkForUpdate.d.ts.map +1 -1
  130. package/lib/typescript/commonjs/error.d.ts +3 -0
  131. package/lib/typescript/commonjs/error.d.ts.map +1 -1
  132. package/lib/typescript/commonjs/fetchJSON.d.ts +6 -0
  133. package/lib/typescript/commonjs/fetchJSON.d.ts.map +1 -0
  134. package/lib/typescript/commonjs/httpClient.d.ts +56 -0
  135. package/lib/typescript/commonjs/httpClient.d.ts.map +1 -0
  136. package/lib/typescript/commonjs/index.d.ts +31 -40
  137. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  138. package/lib/typescript/commonjs/native.d.ts +84 -17
  139. package/lib/typescript/commonjs/native.d.ts.map +1 -1
  140. package/lib/typescript/commonjs/notifyAppReadyAnalytics.d.ts +13 -0
  141. package/lib/typescript/commonjs/notifyAppReadyAnalytics.d.ts.map +1 -0
  142. package/lib/typescript/commonjs/notifyAppReadyAnalytics.test-utils.d.ts +8 -0
  143. package/lib/typescript/commonjs/notifyAppReadyAnalytics.test-utils.d.ts.map +1 -0
  144. package/lib/typescript/commonjs/releaseCatalogCache.d.ts +25 -0
  145. package/lib/typescript/commonjs/releaseCatalogCache.d.ts.map +1 -0
  146. package/lib/typescript/commonjs/sdkVersion.d.ts +1 -1
  147. package/lib/typescript/commonjs/sdkVersion.d.ts.map +1 -1
  148. package/lib/typescript/commonjs/specs/NativeHotUpdater.d.ts +40 -5
  149. package/lib/typescript/commonjs/specs/NativeHotUpdater.d.ts.map +1 -1
  150. package/lib/typescript/commonjs/types.d.ts +0 -118
  151. package/lib/typescript/commonjs/types.d.ts.map +1 -1
  152. package/lib/typescript/commonjs/wrap.d.ts +2 -191
  153. package/lib/typescript/commonjs/wrap.d.ts.map +1 -1
  154. package/lib/typescript/commonjs/wrap.types.d.ts +65 -0
  155. package/lib/typescript/commonjs/wrap.types.d.ts.map +1 -0
  156. package/lib/typescript/module/catalogCacheNative.d.ts +4 -0
  157. package/lib/typescript/module/catalogCacheNative.d.ts.map +1 -0
  158. package/lib/typescript/module/checkForUpdate.d.ts +14 -4
  159. package/lib/typescript/module/checkForUpdate.d.ts.map +1 -1
  160. package/lib/typescript/module/error.d.ts +3 -0
  161. package/lib/typescript/module/error.d.ts.map +1 -1
  162. package/lib/typescript/module/fetchJSON.d.ts +6 -0
  163. package/lib/typescript/module/fetchJSON.d.ts.map +1 -0
  164. package/lib/typescript/module/httpClient.d.ts +56 -0
  165. package/lib/typescript/module/httpClient.d.ts.map +1 -0
  166. package/lib/typescript/module/index.d.ts +31 -40
  167. package/lib/typescript/module/index.d.ts.map +1 -1
  168. package/lib/typescript/module/native.d.ts +84 -17
  169. package/lib/typescript/module/native.d.ts.map +1 -1
  170. package/lib/typescript/module/notifyAppReadyAnalytics.d.ts +13 -0
  171. package/lib/typescript/module/notifyAppReadyAnalytics.d.ts.map +1 -0
  172. package/lib/typescript/module/notifyAppReadyAnalytics.test-utils.d.ts +8 -0
  173. package/lib/typescript/module/notifyAppReadyAnalytics.test-utils.d.ts.map +1 -0
  174. package/lib/typescript/module/releaseCatalogCache.d.ts +25 -0
  175. package/lib/typescript/module/releaseCatalogCache.d.ts.map +1 -0
  176. package/lib/typescript/module/sdkVersion.d.ts +1 -1
  177. package/lib/typescript/module/sdkVersion.d.ts.map +1 -1
  178. package/lib/typescript/module/specs/NativeHotUpdater.d.ts +40 -5
  179. package/lib/typescript/module/specs/NativeHotUpdater.d.ts.map +1 -1
  180. package/lib/typescript/module/types.d.ts +0 -118
  181. package/lib/typescript/module/types.d.ts.map +1 -1
  182. package/lib/typescript/module/wrap.d.ts +2 -191
  183. package/lib/typescript/module/wrap.d.ts.map +1 -1
  184. package/lib/typescript/module/wrap.types.d.ts +65 -0
  185. package/lib/typescript/module/wrap.types.d.ts.map +1 -0
  186. package/package.json +6 -24
  187. package/src/catalogCacheNative.spec.ts +63 -0
  188. package/src/catalogCacheNative.ts +74 -0
  189. package/src/checkForUpdate.releaseCatalog.spec.ts +596 -0
  190. package/src/checkForUpdate.ts +367 -96
  191. package/src/error.ts +7 -0
  192. package/src/{fetchUpdateInfo.ts → fetchJSON.ts} +8 -15
  193. package/src/httpClient.spec.ts +132 -0
  194. package/src/httpClient.ts +261 -0
  195. package/src/index.spec.ts +108 -201
  196. package/src/index.ts +68 -91
  197. package/src/iosInterop.spec.ts +30 -0
  198. package/src/native.spec.ts +226 -10
  199. package/src/native.ts +385 -81
  200. package/src/notifyAppReadyAnalytics.boundary.spec.ts +234 -0
  201. package/src/notifyAppReadyAnalytics.spec.ts +243 -0
  202. package/src/notifyAppReadyAnalytics.test-utils.ts +31 -0
  203. package/src/notifyAppReadyAnalytics.transport.spec.ts +130 -0
  204. package/src/notifyAppReadyAnalytics.ts +194 -0
  205. package/src/releaseCatalogCache.spec.ts +282 -0
  206. package/src/releaseCatalogCache.ts +341 -0
  207. package/src/releaseCatalogCacheNativeContract.spec.ts +80 -0
  208. package/src/sdkVersion.ts +1 -1
  209. package/src/specs/NativeHotUpdater.ts +51 -5
  210. package/src/types.ts +0 -140
  211. package/src/wrap.spec.ts +251 -56
  212. package/src/wrap.tsx +23 -318
  213. package/src/wrap.types.ts +78 -0
  214. package/android/src/main/java/com/hotupdater/StringResourceUtils.kt +0 -45
  215. package/app.plugin.js +0 -1
  216. package/ios/HotUpdater/Internal/HotUpdaterCrashHandler.h +0 -7
  217. package/ios/HotUpdater/Internal/HotUpdaterCrashHandler.mm +0 -4
  218. package/lib/commonjs/DefaultResolver.js +0 -50
  219. package/lib/commonjs/DefaultResolver.js.map +0 -1
  220. package/lib/commonjs/DefaultResolver.spec.js +0 -144
  221. package/lib/commonjs/DefaultResolver.spec.js.map +0 -1
  222. package/lib/commonjs/fetchUpdateInfo.js.map +0 -1
  223. package/lib/module/DefaultResolver.js +0 -46
  224. package/lib/module/DefaultResolver.js.map +0 -1
  225. package/lib/module/DefaultResolver.spec.js +0 -144
  226. package/lib/module/DefaultResolver.spec.js.map +0 -1
  227. package/lib/module/fetchUpdateInfo.js.map +0 -1
  228. package/lib/typescript/commonjs/DefaultResolver.d.ts +0 -11
  229. package/lib/typescript/commonjs/DefaultResolver.d.ts.map +0 -1
  230. package/lib/typescript/commonjs/fetchUpdateInfo.d.ts +0 -7
  231. package/lib/typescript/commonjs/fetchUpdateInfo.d.ts.map +0 -1
  232. package/lib/typescript/module/DefaultResolver.d.ts +0 -11
  233. package/lib/typescript/module/DefaultResolver.d.ts.map +0 -1
  234. package/lib/typescript/module/fetchUpdateInfo.d.ts +0 -7
  235. package/lib/typescript/module/fetchUpdateInfo.d.ts.map +0 -1
  236. package/plugin/build/transformers.js +0 -314
  237. package/plugin/build/withHotUpdater.js +0 -228
  238. package/src/DefaultResolver.spec.ts +0 -193
  239. package/src/DefaultResolver.ts +0 -63
package/src/index.spec.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { beforeEach, describe, expect, it, vi } from "vitest";
2
2
 
3
- import type { HotUpdater as HotUpdaterValue } from "./index";
4
3
  import type { HotUpdaterInitOptions, HotUpdaterOptions } from "./wrap";
5
4
 
6
5
  const mocks = vi.hoisted(() => {
@@ -12,9 +11,15 @@ const mocks = vi.hoisted(() => {
12
11
 
13
12
  return {
14
13
  addListener: vi.fn(() => () => {}),
15
- checkForUpdate: vi.fn(),
14
+ checkForUpdate: vi.fn(async () => null),
16
15
  clearCrashHistory: vi.fn(() => true),
17
- createDefaultResolver: vi.fn(),
16
+ createHttpClient: vi.fn((baseURL: unknown) => ({ baseURL })),
17
+ getActiveUpdateState: vi.fn(() => ({
18
+ activeSelection: null,
19
+ highestSeenCatalogs: {},
20
+ stableSelection: null,
21
+ verificationPending: false,
22
+ })),
18
23
  getAppVersion: vi.fn(() => "1.0.0"),
19
24
  getBaseURL: vi.fn(() => null),
20
25
  getBundleId: vi.fn(() => "bundle-id"),
@@ -23,21 +28,25 @@ const mocks = vi.hoisted(() => {
23
28
  getCrashHistory: vi.fn(() => []),
24
29
  getDefaultChannel: vi.fn(() => "production"),
25
30
  getFingerprintHash: vi.fn(() => null),
31
+ getInstallId: vi.fn(() => "install-id"),
26
32
  getManifest: vi.fn(() => null),
27
33
  getMinBundleId: vi.fn(() => "min-bundle-id"),
34
+ getReleaseId: vi.fn(async () => null),
28
35
  init: vi.fn(),
29
36
  isChannelSwitched: vi.fn(() => false),
37
+ notifyAppReady: vi.fn(() => ({ status: "UNCHANGED" as const })),
30
38
  reload: vi.fn(),
31
39
  resetChannel: vi.fn(),
32
40
  setCohort: vi.fn(),
33
41
  setReloadBehavior: vi.fn(),
42
+ setUser: vi.fn(),
34
43
  updateBundle: vi.fn(),
35
- wrap: vi.fn(),
44
+ wrap: vi.fn((Component: unknown) => Component),
36
45
  };
37
46
  });
38
47
 
39
- vi.mock("./DefaultResolver", () => ({
40
- createDefaultResolver: mocks.createDefaultResolver,
48
+ vi.mock("./httpClient", () => ({
49
+ createHttpClient: mocks.createHttpClient,
41
50
  }));
42
51
 
43
52
  vi.mock("./checkForUpdate", () => ({
@@ -47,6 +56,7 @@ vi.mock("./checkForUpdate", () => ({
47
56
  vi.mock("./native", () => ({
48
57
  addListener: mocks.addListener,
49
58
  clearCrashHistory: mocks.clearCrashHistory,
59
+ getPublicActiveUpdateState: mocks.getActiveUpdateState,
50
60
  getAppVersion: mocks.getAppVersion,
51
61
  getBaseURL: mocks.getBaseURL,
52
62
  getBundleId: mocks.getBundleId,
@@ -55,13 +65,17 @@ vi.mock("./native", () => ({
55
65
  getCrashHistory: mocks.getCrashHistory,
56
66
  getDefaultChannel: mocks.getDefaultChannel,
57
67
  getFingerprintHash: mocks.getFingerprintHash,
68
+ getInstallId: mocks.getInstallId,
58
69
  getManifest: mocks.getManifest,
59
70
  getMinBundleId: mocks.getMinBundleId,
71
+ getReleaseId: mocks.getReleaseId,
60
72
  isChannelSwitched: mocks.isChannelSwitched,
73
+ notifyAppReady: mocks.notifyAppReady,
61
74
  reload: mocks.reload,
62
75
  resetChannel: mocks.resetChannel,
63
76
  setCohort: mocks.setCohort,
64
77
  setReloadBehavior: mocks.setReloadBehavior,
78
+ setUser: mocks.setUser,
65
79
  updateBundle: mocks.updateBundle,
66
80
  }));
67
81
 
@@ -70,184 +84,138 @@ vi.mock("./wrap", () => ({
70
84
  wrap: mocks.wrap,
71
85
  }));
72
86
 
73
- const importHotUpdater = async () => {
74
- const { HotUpdater } = await import("./index");
75
- return HotUpdater;
76
- };
87
+ const importHotUpdater = async () => (await import("./index")).HotUpdater;
77
88
 
78
89
  describe("HotUpdater client initialization", () => {
79
90
  beforeEach(() => {
80
91
  vi.resetModules();
81
-
82
- for (const mock of Object.values(mocks)) {
83
- mock.mockReset();
84
- }
85
-
86
- mocks.addListener.mockReturnValue(() => {});
87
- mocks.checkForUpdate.mockResolvedValue(null);
88
- mocks.createDefaultResolver.mockImplementation((baseURL: unknown) => ({
92
+ vi.clearAllMocks();
93
+ mocks.createHttpClient.mockImplementation((baseURL: unknown) => ({
89
94
  baseURL,
90
- checkUpdate: vi.fn(),
91
- notifyAppReady: vi.fn(),
92
95
  }));
93
- mocks.getBaseURL.mockReturnValue(null);
94
- mocks.init.mockReturnValue(undefined);
95
- mocks.wrap.mockReturnValue((Component: unknown) => Component);
96
+ mocks.checkForUpdate.mockResolvedValue(null);
97
+ mocks.wrap.mockImplementation((Component: unknown) => Component);
96
98
  });
97
99
 
98
- it("initializes manual update flows without wrapping a component", async () => {
99
- const resolver = {
100
- checkUpdate: vi.fn(),
101
- notifyAppReady: vi.fn(),
102
- };
103
- mocks.createDefaultResolver.mockReturnValue(resolver);
104
-
100
+ it("initializes a private HTTP client from the required baseURL", async () => {
101
+ const client = { createSession: vi.fn() };
102
+ mocks.createHttpClient.mockReturnValue(client as never);
105
103
  const HotUpdater = await importHotUpdater();
106
104
 
107
- const result = HotUpdater.init({
105
+ HotUpdater.init({
106
+ analytics: true,
108
107
  baseURL: "https://updates.example.com",
109
- requestHeaders: {
110
- Authorization: "Bearer token",
111
- },
108
+ requestHeaders: { Authorization: "Bearer token" },
112
109
  requestTimeout: 1000,
113
110
  });
114
111
 
115
- expect(result).toBeUndefined();
116
- expect(mocks.createDefaultResolver).toHaveBeenCalledWith(
112
+ expect(mocks.createHttpClient).toHaveBeenCalledWith(
117
113
  "https://updates.example.com",
118
114
  );
119
115
  expect(mocks.init).toHaveBeenCalledWith({
120
- requestHeaders: {
121
- Authorization: "Bearer token",
122
- },
116
+ analytics: true,
117
+ client,
118
+ requestHeaders: { Authorization: "Bearer token" },
123
119
  requestTimeout: 1000,
124
- resolver,
125
120
  });
126
121
  });
127
122
 
128
- it("accepts dynamic baseURL resolvers for manual update flows", async () => {
129
- const resolver = {
130
- checkUpdate: vi.fn(),
131
- notifyAppReady: vi.fn(),
132
- };
123
+ it("accepts a functional baseURL without resolving it during init", async () => {
133
124
  const resolveBaseURL = vi.fn(() => "https://updates.example.com");
134
- mocks.createDefaultResolver.mockReturnValue(resolver);
135
-
136
125
  const HotUpdater = await importHotUpdater();
137
126
 
138
- HotUpdater.init({
139
- baseURL: resolveBaseURL,
140
- });
127
+ HotUpdater.init({ baseURL: resolveBaseURL });
141
128
 
142
- expect(mocks.createDefaultResolver).toHaveBeenCalledWith(resolveBaseURL);
143
- expect(mocks.init).toHaveBeenCalledWith({
144
- resolver,
145
- });
129
+ expect(mocks.createHttpClient).toHaveBeenCalledWith(resolveBaseURL);
130
+ expect(resolveBaseURL).not.toHaveBeenCalled();
146
131
  });
147
132
 
148
- it("accepts custom resolvers for manual update flows", async () => {
149
- const resolver = {
150
- checkUpdate: vi.fn(),
151
- notifyAppReady: vi.fn(),
152
- };
153
-
133
+ it("requires baseURL and rejects the removed resolver shape", async () => {
154
134
  const HotUpdater = await importHotUpdater();
155
135
 
156
- HotUpdater.init({
157
- resolver,
158
- requestHeaders: {
159
- Authorization: "Bearer token",
160
- },
161
- });
162
-
163
- expect(mocks.createDefaultResolver).not.toHaveBeenCalled();
164
- expect(mocks.init).toHaveBeenCalledWith({
165
- resolver,
166
- requestHeaders: {
167
- Authorization: "Bearer token",
168
- },
169
- });
136
+ expect(() => HotUpdater.init({} as never)).toThrow(
137
+ "baseURL must be provided",
138
+ );
139
+ expect(() => HotUpdater.init({ resolver: {} } as never)).toThrow(
140
+ "baseURL must be provided",
141
+ );
142
+ expect(mocks.init).not.toHaveBeenCalled();
170
143
  });
171
144
 
172
- it("accepts onError during init and uses it for later manual update checks", async () => {
173
- const resolver = {
174
- checkUpdate: vi.fn(),
175
- notifyAppReady: vi.fn(),
176
- };
177
- const onError = vi.fn();
178
- mocks.createDefaultResolver.mockReturnValue(resolver);
179
-
180
- const HotUpdater = await importHotUpdater();
181
-
182
- HotUpdater.init({
145
+ it("types init and wrap with baseURL but no resolver or catalogId", () => {
146
+ const initOptions = {
183
147
  baseURL: "https://updates.example.com",
184
- onError,
185
- });
186
-
187
- await HotUpdater.checkForUpdate({
148
+ } satisfies HotUpdaterInitOptions;
149
+ const wrapOptions = {
150
+ baseURL: async () => "https://updates.example.com",
188
151
  updateStrategy: "appVersion",
189
- });
152
+ } satisfies HotUpdaterOptions;
153
+
154
+ const assertRemovedInputsStayRejected = () => {
155
+ // @ts-expect-error baseURL is required
156
+ const missingBaseURL: HotUpdaterInitOptions = {};
157
+ // @ts-expect-error resolver is no longer a public input
158
+ const customResolver: HotUpdaterInitOptions = { resolver: {} };
159
+ const clientCatalog: HotUpdaterInitOptions = {
160
+ // @ts-expect-error catalogId is internal protocol metadata
161
+ catalogId: "project-a",
162
+ baseURL: "https://updates.example.com",
163
+ };
164
+ void missingBaseURL;
165
+ void customResolver;
166
+ void clientCatalog;
167
+ };
190
168
 
191
- expect(mocks.init).toHaveBeenCalledWith({
192
- onError,
193
- resolver,
194
- });
195
- expect(mocks.checkForUpdate).toHaveBeenCalledWith({
196
- onError,
197
- requestHeaders: {},
198
- requestTimeout: undefined,
199
- resolver,
200
- updateStrategy: "appVersion",
201
- });
169
+ expect(assertRemovedInputsStayRejected).toBeTypeOf("function");
170
+ expect(initOptions.baseURL).toBe("https://updates.example.com");
171
+ expect(wrapOptions.updateStrategy).toBe("appVersion");
202
172
  });
203
173
 
204
- it("lets checkForUpdate override the init onError handler", async () => {
205
- const resolver = {
206
- checkUpdate: vi.fn(),
207
- notifyAppReady: vi.fn(),
208
- };
209
- const initOnError = vi.fn();
174
+ it("merges settings and carries the analytics gate to checks", async () => {
175
+ const client = { createSession: vi.fn() };
176
+ mocks.createHttpClient.mockReturnValue(client as never);
210
177
  const checkOnError = vi.fn();
211
- mocks.createDefaultResolver.mockReturnValue(resolver);
212
-
213
178
  const HotUpdater = await importHotUpdater();
214
-
215
179
  HotUpdater.init({
180
+ analytics: true,
216
181
  baseURL: "https://updates.example.com",
217
- onError: initOnError,
182
+ requestHeaders: { Authorization: "Bearer token" },
183
+ requestTimeout: 1000,
218
184
  });
219
185
 
220
186
  await HotUpdater.checkForUpdate({
221
187
  onError: checkOnError,
188
+ requestHeaders: { "X-Runtime": "secondary" },
222
189
  updateStrategy: "appVersion",
223
190
  });
224
191
 
225
192
  expect(mocks.checkForUpdate).toHaveBeenCalledWith({
193
+ analytics: true,
194
+ client,
226
195
  onError: checkOnError,
227
- requestHeaders: {},
228
- requestTimeout: undefined,
229
- resolver,
196
+ requestHeaders: {
197
+ Authorization: "Bearer token",
198
+ "X-Runtime": "secondary",
199
+ },
200
+ requestTimeout: 1000,
230
201
  updateStrategy: "appVersion",
231
202
  });
232
203
  });
233
204
 
234
- it("defaults wrap to automatic update mode", async () => {
235
- const resolver = {
236
- checkUpdate: vi.fn(),
237
- notifyAppReady: vi.fn(),
238
- };
239
- mocks.createDefaultResolver.mockReturnValue(resolver);
240
-
205
+ it("normalizes wrap with the same private client contract", async () => {
206
+ const client = { createSession: vi.fn() };
207
+ mocks.createHttpClient.mockReturnValue(client as never);
241
208
  const HotUpdater = await importHotUpdater();
242
209
 
243
210
  HotUpdater.wrap({
211
+ analytics: true,
244
212
  baseURL: "https://updates.example.com",
245
213
  updateStrategy: "appVersion",
246
214
  });
247
215
 
248
216
  expect(mocks.wrap).toHaveBeenCalledWith({
249
- resolver,
250
- updateMode: "auto",
217
+ analytics: true,
218
+ client,
251
219
  updateStrategy: "appVersion",
252
220
  });
253
221
  });
@@ -292,95 +260,34 @@ describe("HotUpdater client initialization", () => {
292
260
  },
293
261
  );
294
262
 
295
- it("keeps deprecated manual wrap calls working", async () => {
296
- const resolver = {
297
- checkUpdate: vi.fn(),
298
- notifyAppReady: vi.fn(),
299
- };
300
- mocks.createDefaultResolver.mockReturnValue(resolver);
301
-
302
- const HotUpdater = await importHotUpdater();
303
-
304
- HotUpdater.wrap({
305
- baseURL: "https://updates.example.com",
306
- updateMode: "manual",
307
- });
308
-
309
- expect(mocks.wrap).toHaveBeenCalledWith({
310
- resolver,
311
- updateMode: "manual",
312
- });
313
- });
314
-
315
- it("types public wrap to accept pre-typed option unions", () => {
316
- const compileOnly = (
317
- wrap: typeof HotUpdaterValue.wrap,
318
- options: HotUpdaterOptions,
319
- ) => wrap(options);
320
-
321
- expect(compileOnly).toBeTypeOf("function");
322
- });
323
-
324
- it("types public init options with onError", () => {
325
- const options = {
326
- baseURL: "https://updates.example.com",
327
- onError: vi.fn(),
328
- } satisfies HotUpdaterInitOptions;
329
-
330
- expect(options.baseURL).toBe("https://updates.example.com");
331
- });
332
-
333
- it("uses init configuration for later manual update checks", async () => {
334
- const resolver = {
335
- checkUpdate: vi.fn(),
336
- notifyAppReady: vi.fn(),
337
- };
338
- mocks.createDefaultResolver.mockReturnValue(resolver);
339
-
263
+ it("rejects removed manual wrap options", async () => {
340
264
  const HotUpdater = await importHotUpdater();
341
265
 
342
- HotUpdater.init({
343
- baseURL: "https://updates.example.com",
344
- requestHeaders: {
345
- Authorization: "Bearer token",
346
- },
347
- requestTimeout: 1000,
348
- });
349
-
350
- await HotUpdater.checkForUpdate({
351
- requestHeaders: {
352
- "X-Runtime": "secondary",
353
- },
354
- updateStrategy: "appVersion",
355
- });
356
-
357
- expect(mocks.checkForUpdate).toHaveBeenCalledWith({
358
- requestHeaders: {
359
- Authorization: "Bearer token",
360
- "X-Runtime": "secondary",
361
- },
362
- requestTimeout: 1000,
363
- resolver,
364
- updateStrategy: "appVersion",
365
- });
266
+ expect(() =>
267
+ HotUpdater.wrap({
268
+ baseURL: "https://updates.example.com",
269
+ updateMode: "manual",
270
+ } as never),
271
+ ).toThrow('HotUpdater.wrap({ updateMode: "manual" }) was removed');
366
272
  });
367
273
 
368
- it("points users to wrap or init when methods are called too early", async () => {
274
+ it("requires initialization before manual update APIs", async () => {
369
275
  const HotUpdater = await importHotUpdater();
370
276
 
371
277
  expect(() =>
372
- HotUpdater.checkForUpdate({
373
- updateStrategy: "appVersion",
374
- }),
278
+ HotUpdater.checkForUpdate({ updateStrategy: "appVersion" }),
375
279
  ).toThrow("requires HotUpdater.wrap() or HotUpdater.init() to be used");
376
280
  });
377
281
 
378
- it("requires baseURL for init", async () => {
282
+ it("preserves native identity and user APIs", async () => {
379
283
  const HotUpdater = await importHotUpdater();
380
284
 
381
- expect(() => HotUpdater.init({} as never)).toThrow(
382
- "Either baseURL or resolver must be provided",
383
- );
384
- expect(mocks.init).not.toHaveBeenCalled();
285
+ expect(HotUpdater.getInstallId()).toBe("install-id");
286
+ expect(HotUpdater.getMinBundleId()).toBe("min-bundle-id");
287
+ HotUpdater.setUser({ userId: "user-123", username: "alice" });
288
+ expect(mocks.setUser).toHaveBeenCalledWith({
289
+ userId: "user-123",
290
+ username: "alice",
291
+ });
385
292
  });
386
293
  });