@hot-updater/react-native 1.0.0-rc.17 → 1.0.0-rc.21

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 (240) hide show
  1. package/lib/commonjs/checkForUpdate.js +7 -9
  2. package/lib/commonjs/checkForUpdate.js.map +1 -1
  3. package/lib/commonjs/clientPlugin.js +7 -43
  4. package/lib/commonjs/clientPlugin.js.map +1 -1
  5. package/lib/commonjs/httpClient.js +7 -9
  6. package/lib/commonjs/httpClient.js.map +1 -1
  7. package/lib/commonjs/index.js +10 -0
  8. package/lib/commonjs/index.js.map +1 -1
  9. package/lib/commonjs/native.js +4 -4
  10. package/lib/commonjs/native.js.map +1 -1
  11. package/lib/commonjs/pluginHost.js +26 -190
  12. package/lib/commonjs/pluginHost.js.map +1 -1
  13. package/lib/commonjs/releaseCatalogCache.js +7 -59
  14. package/lib/commonjs/releaseCatalogCache.js.map +1 -1
  15. package/lib/commonjs/sdkVersion.js +1 -1
  16. package/lib/module/checkForUpdate.js +1 -3
  17. package/lib/module/checkForUpdate.js.map +1 -1
  18. package/lib/module/clientPlugin.js +1 -41
  19. package/lib/module/clientPlugin.js.map +1 -1
  20. package/lib/module/httpClient.js +1 -3
  21. package/lib/module/httpClient.js.map +1 -1
  22. package/lib/module/index.js +2 -0
  23. package/lib/module/index.js.map +1 -1
  24. package/lib/module/native.js +1 -1
  25. package/lib/module/native.js.map +1 -1
  26. package/lib/module/pluginHost.js +22 -187
  27. package/lib/module/pluginHost.js.map +1 -1
  28. package/lib/module/releaseCatalogCache.js +3 -54
  29. package/lib/module/releaseCatalogCache.js.map +1 -1
  30. package/lib/module/sdkVersion.js +1 -1
  31. package/lib/typescript/commonjs/checkForUpdate.d.ts.map +1 -1
  32. package/lib/typescript/commonjs/clientPlugin.d.ts +1 -184
  33. package/lib/typescript/commonjs/clientPlugin.d.ts.map +1 -1
  34. package/lib/typescript/commonjs/httpClient.d.ts +1 -2
  35. package/lib/typescript/commonjs/httpClient.d.ts.map +1 -1
  36. package/lib/typescript/commonjs/index.d.ts +1 -0
  37. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  38. package/lib/typescript/commonjs/native.d.ts +1 -1
  39. package/lib/typescript/commonjs/native.d.ts.map +1 -1
  40. package/lib/typescript/commonjs/pluginHost.d.ts +3 -28
  41. package/lib/typescript/commonjs/pluginHost.d.ts.map +1 -1
  42. package/lib/typescript/commonjs/releaseCatalogCache.d.ts +1 -13
  43. package/lib/typescript/commonjs/releaseCatalogCache.d.ts.map +1 -1
  44. package/lib/typescript/commonjs/sdkVersion.d.ts +1 -1
  45. package/lib/typescript/commonjs/types.d.ts +1 -1
  46. package/lib/typescript/commonjs/types.d.ts.map +1 -1
  47. package/lib/typescript/commonjs/wrap.types.d.ts +2 -2
  48. package/lib/typescript/module/checkForUpdate.d.ts.map +1 -1
  49. package/lib/typescript/module/clientPlugin.d.ts +1 -184
  50. package/lib/typescript/module/clientPlugin.d.ts.map +1 -1
  51. package/lib/typescript/module/httpClient.d.ts +1 -2
  52. package/lib/typescript/module/httpClient.d.ts.map +1 -1
  53. package/lib/typescript/module/index.d.ts +1 -0
  54. package/lib/typescript/module/index.d.ts.map +1 -1
  55. package/lib/typescript/module/native.d.ts +1 -1
  56. package/lib/typescript/module/native.d.ts.map +1 -1
  57. package/lib/typescript/module/pluginHost.d.ts +3 -28
  58. package/lib/typescript/module/pluginHost.d.ts.map +1 -1
  59. package/lib/typescript/module/releaseCatalogCache.d.ts +1 -13
  60. package/lib/typescript/module/releaseCatalogCache.d.ts.map +1 -1
  61. package/lib/typescript/module/sdkVersion.d.ts +1 -1
  62. package/lib/typescript/module/types.d.ts +1 -1
  63. package/lib/typescript/module/types.d.ts.map +1 -1
  64. package/lib/typescript/module/wrap.types.d.ts +2 -2
  65. package/package.json +7 -16
  66. package/src/checkForUpdate.ts +4 -6
  67. package/src/clientPlugin.ts +17 -231
  68. package/src/httpClient.ts +4 -4
  69. package/src/index.ts +7 -0
  70. package/src/native.ts +1 -1
  71. package/src/pluginHost.ts +24 -241
  72. package/src/releaseCatalogCache.ts +7 -136
  73. package/src/sdkVersion.ts +1 -1
  74. package/src/types.ts +1 -1
  75. package/src/wrap.types.ts +2 -2
  76. package/android/src/test/java/com/hotupdater/BsdiffPatchTest.kt +0 -46
  77. package/android/src/test/java/com/hotupdater/BundleFileStorageServiceTest.kt +0 -2236
  78. package/android/src/test/java/com/hotupdater/HotUpdaterExceptionTest.kt +0 -220
  79. package/android/src/test/java/com/hotupdater/HotUpdaterImplTest.kt +0 -264
  80. package/android/src/test/java/com/hotupdater/HotUpdaterRecoveryStateTest.kt +0 -97
  81. package/android/src/test/java/com/hotupdater/InstallIdentityServiceTest.kt +0 -71
  82. package/android/src/test/java/com/hotupdater/KeyValueStorageServiceTest.kt +0 -106
  83. package/android/src/test/java/com/hotupdater/NativeConfigUtilsTest.kt +0 -20
  84. package/android/src/test/java/com/hotupdater/NoBackupContext.kt +0 -11
  85. package/android/src/test/java/com/hotupdater/OkHttpDownloadServiceTest.kt +0 -397
  86. package/android/src/test/java/com/hotupdater/PendingCrashRecoveryTest.kt +0 -44
  87. package/android/src/test/java/com/hotupdater/PreviousProcessExitTest.kt +0 -57
  88. package/android/src/test/java/com/hotupdater/RelativePathResolverTest.kt +0 -41
  89. package/android/src/test/java/com/hotupdater/ReleaseCatalogCacheServiceTest.kt +0 -118
  90. package/android/src/test/java/com/hotupdater/TarBrArchiveExtractorTest.kt +0 -206
  91. package/lib/commonjs/appReady.spec.js +0 -360
  92. package/lib/commonjs/appReady.spec.js.map +0 -1
  93. package/lib/commonjs/appReady.test-utils.js +0 -25
  94. package/lib/commonjs/appReady.test-utils.js.map +0 -1
  95. package/lib/commonjs/baseURL.js +0 -16
  96. package/lib/commonjs/baseURL.js.map +0 -1
  97. package/lib/commonjs/catalogCacheNative.spec.js +0 -31
  98. package/lib/commonjs/catalogCacheNative.spec.js.map +0 -1
  99. package/lib/commonjs/checkForUpdate.releaseCatalog.spec.js +0 -936
  100. package/lib/commonjs/checkForUpdate.releaseCatalog.spec.js.map +0 -1
  101. package/lib/commonjs/entryImportGraph.spec.js +0 -50
  102. package/lib/commonjs/entryImportGraph.spec.js.map +0 -1
  103. package/lib/commonjs/httpClient.spec.js +0 -171
  104. package/lib/commonjs/httpClient.spec.js.map +0 -1
  105. package/lib/commonjs/index.spec.js +0 -395
  106. package/lib/commonjs/index.spec.js.map +0 -1
  107. package/lib/commonjs/iosInterop.spec.js +0 -18
  108. package/lib/commonjs/iosInterop.spec.js.map +0 -1
  109. package/lib/commonjs/native.spec.js +0 -910
  110. package/lib/commonjs/native.spec.js.map +0 -1
  111. package/lib/commonjs/pluginHost.spec.js +0 -292
  112. package/lib/commonjs/pluginHost.spec.js.map +0 -1
  113. package/lib/commonjs/plugins/insights/eventId.js +0 -129
  114. package/lib/commonjs/plugins/insights/eventId.js.map +0 -1
  115. package/lib/commonjs/plugins/insights/eventId.spec.js +0 -47
  116. package/lib/commonjs/plugins/insights/eventId.spec.js.map +0 -1
  117. package/lib/commonjs/plugins/insights/index.js +0 -272
  118. package/lib/commonjs/plugins/insights/index.js.map +0 -1
  119. package/lib/commonjs/plugins/insights/insights.spec.js +0 -640
  120. package/lib/commonjs/plugins/insights/insights.spec.js.map +0 -1
  121. package/lib/commonjs/plugins/insights/sender.js +0 -128
  122. package/lib/commonjs/plugins/insights/sender.js.map +0 -1
  123. package/lib/commonjs/plugins/insights/sender.spec.js +0 -265
  124. package/lib/commonjs/plugins/insights/sender.spec.js.map +0 -1
  125. package/lib/commonjs/plugins/insights/state.js +0 -145
  126. package/lib/commonjs/plugins/insights/state.js.map +0 -1
  127. package/lib/commonjs/releaseCatalogCache.spec.js +0 -213
  128. package/lib/commonjs/releaseCatalogCache.spec.js.map +0 -1
  129. package/lib/commonjs/releaseCatalogCacheNativeContract.spec.js +0 -64
  130. package/lib/commonjs/releaseCatalogCacheNativeContract.spec.js.map +0 -1
  131. package/lib/commonjs/store.notification.spec.js +0 -84
  132. package/lib/commonjs/store.notification.spec.js.map +0 -1
  133. package/lib/commonjs/store.spec.js +0 -182
  134. package/lib/commonjs/store.spec.js.map +0 -1
  135. package/lib/commonjs/updateError.spec.js +0 -149
  136. package/lib/commonjs/updateError.spec.js.map +0 -1
  137. package/lib/commonjs/wrap.progress.spec.js +0 -195
  138. package/lib/commonjs/wrap.progress.spec.js.map +0 -1
  139. package/lib/commonjs/wrap.spec.js +0 -232
  140. package/lib/commonjs/wrap.spec.js.map +0 -1
  141. package/lib/module/appReady.spec.js +0 -359
  142. package/lib/module/appReady.spec.js.map +0 -1
  143. package/lib/module/appReady.test-utils.js +0 -19
  144. package/lib/module/appReady.test-utils.js.map +0 -1
  145. package/lib/module/baseURL.js +0 -11
  146. package/lib/module/baseURL.js.map +0 -1
  147. package/lib/module/catalogCacheNative.spec.js +0 -31
  148. package/lib/module/catalogCacheNative.spec.js.map +0 -1
  149. package/lib/module/checkForUpdate.releaseCatalog.spec.js +0 -935
  150. package/lib/module/checkForUpdate.releaseCatalog.spec.js.map +0 -1
  151. package/lib/module/entryImportGraph.spec.js +0 -50
  152. package/lib/module/entryImportGraph.spec.js.map +0 -1
  153. package/lib/module/httpClient.spec.js +0 -171
  154. package/lib/module/httpClient.spec.js.map +0 -1
  155. package/lib/module/index.spec.js +0 -394
  156. package/lib/module/index.spec.js.map +0 -1
  157. package/lib/module/iosInterop.spec.js +0 -18
  158. package/lib/module/iosInterop.spec.js.map +0 -1
  159. package/lib/module/native.spec.js +0 -909
  160. package/lib/module/native.spec.js.map +0 -1
  161. package/lib/module/pluginHost.spec.js +0 -291
  162. package/lib/module/pluginHost.spec.js.map +0 -1
  163. package/lib/module/plugins/insights/eventId.js +0 -122
  164. package/lib/module/plugins/insights/eventId.js.map +0 -1
  165. package/lib/module/plugins/insights/eventId.spec.js +0 -47
  166. package/lib/module/plugins/insights/eventId.spec.js.map +0 -1
  167. package/lib/module/plugins/insights/index.js +0 -268
  168. package/lib/module/plugins/insights/index.js.map +0 -1
  169. package/lib/module/plugins/insights/insights.spec.js +0 -639
  170. package/lib/module/plugins/insights/insights.spec.js.map +0 -1
  171. package/lib/module/plugins/insights/sender.js +0 -123
  172. package/lib/module/plugins/insights/sender.js.map +0 -1
  173. package/lib/module/plugins/insights/sender.spec.js +0 -265
  174. package/lib/module/plugins/insights/sender.spec.js.map +0 -1
  175. package/lib/module/plugins/insights/state.js +0 -139
  176. package/lib/module/plugins/insights/state.js.map +0 -1
  177. package/lib/module/releaseCatalogCache.spec.js +0 -213
  178. package/lib/module/releaseCatalogCache.spec.js.map +0 -1
  179. package/lib/module/releaseCatalogCacheNativeContract.spec.js +0 -64
  180. package/lib/module/releaseCatalogCacheNativeContract.spec.js.map +0 -1
  181. package/lib/module/store.notification.spec.js +0 -85
  182. package/lib/module/store.notification.spec.js.map +0 -1
  183. package/lib/module/store.spec.js +0 -181
  184. package/lib/module/store.spec.js.map +0 -1
  185. package/lib/module/updateError.spec.js +0 -149
  186. package/lib/module/updateError.spec.js.map +0 -1
  187. package/lib/module/wrap.progress.spec.js +0 -196
  188. package/lib/module/wrap.progress.spec.js.map +0 -1
  189. package/lib/module/wrap.spec.js +0 -233
  190. package/lib/module/wrap.spec.js.map +0 -1
  191. package/lib/typescript/commonjs/appReady.test-utils.d.ts +0 -9
  192. package/lib/typescript/commonjs/appReady.test-utils.d.ts.map +0 -1
  193. package/lib/typescript/commonjs/baseURL.d.ts +0 -4
  194. package/lib/typescript/commonjs/baseURL.d.ts.map +0 -1
  195. package/lib/typescript/commonjs/plugins/insights/eventId.d.ts +0 -18
  196. package/lib/typescript/commonjs/plugins/insights/eventId.d.ts.map +0 -1
  197. package/lib/typescript/commonjs/plugins/insights/index.d.ts +0 -40
  198. package/lib/typescript/commonjs/plugins/insights/index.d.ts.map +0 -1
  199. package/lib/typescript/commonjs/plugins/insights/sender.d.ts +0 -74
  200. package/lib/typescript/commonjs/plugins/insights/sender.d.ts.map +0 -1
  201. package/lib/typescript/commonjs/plugins/insights/state.d.ts +0 -46
  202. package/lib/typescript/commonjs/plugins/insights/state.d.ts.map +0 -1
  203. package/lib/typescript/module/appReady.test-utils.d.ts +0 -9
  204. package/lib/typescript/module/appReady.test-utils.d.ts.map +0 -1
  205. package/lib/typescript/module/baseURL.d.ts +0 -4
  206. package/lib/typescript/module/baseURL.d.ts.map +0 -1
  207. package/lib/typescript/module/plugins/insights/eventId.d.ts +0 -18
  208. package/lib/typescript/module/plugins/insights/eventId.d.ts.map +0 -1
  209. package/lib/typescript/module/plugins/insights/index.d.ts +0 -40
  210. package/lib/typescript/module/plugins/insights/index.d.ts.map +0 -1
  211. package/lib/typescript/module/plugins/insights/sender.d.ts +0 -74
  212. package/lib/typescript/module/plugins/insights/sender.d.ts.map +0 -1
  213. package/lib/typescript/module/plugins/insights/state.d.ts +0 -46
  214. package/lib/typescript/module/plugins/insights/state.d.ts.map +0 -1
  215. package/plugins/insights/package.json +0 -8
  216. package/src/appReady.spec.ts +0 -393
  217. package/src/appReady.test-utils.ts +0 -31
  218. package/src/baseURL.ts +0 -15
  219. package/src/catalogCacheNative.spec.ts +0 -63
  220. package/src/checkForUpdate.releaseCatalog.spec.ts +0 -966
  221. package/src/entryImportGraph.spec.ts +0 -65
  222. package/src/httpClient.spec.ts +0 -216
  223. package/src/index.spec.ts +0 -434
  224. package/src/iosInterop.spec.ts +0 -30
  225. package/src/native.spec.ts +0 -978
  226. package/src/pluginHost.spec.ts +0 -297
  227. package/src/plugins/insights/eventId.spec.ts +0 -60
  228. package/src/plugins/insights/eventId.ts +0 -171
  229. package/src/plugins/insights/index.ts +0 -367
  230. package/src/plugins/insights/insights.spec.ts +0 -732
  231. package/src/plugins/insights/sender.spec.ts +0 -287
  232. package/src/plugins/insights/sender.ts +0 -221
  233. package/src/plugins/insights/state.ts +0 -184
  234. package/src/releaseCatalogCache.spec.ts +0 -304
  235. package/src/releaseCatalogCacheNativeContract.spec.ts +0 -80
  236. package/src/store.notification.spec.ts +0 -102
  237. package/src/store.spec.ts +0 -215
  238. package/src/updateError.spec.ts +0 -144
  239. package/src/wrap.progress.spec.ts +0 -232
  240. package/src/wrap.spec.ts +0 -262
@@ -1,393 +0,0 @@
1
- import { beforeEach, describe, expect, it, vi } from "vitest";
2
-
3
- import { createNotifyReadResult, stubNotifyFrame } from "./appReady.test-utils";
4
- import type {
5
- AppReadyResult,
6
- HotUpdaterClientHooks,
7
- HotUpdaterClientPlugin,
8
- } from "./clientPlugin";
9
- import type {
10
- ActiveUpdateState,
11
- LaunchTransition,
12
- NotifyAppReadyResult,
13
- } from "./native";
14
-
15
- vi.mock("react-native", () => ({
16
- Platform: { OS: "ios" },
17
- }));
18
-
19
- const mocks = vi.hoisted(() => {
20
- Reflect.set(globalThis, "HotUpdater", { SDK_VERSION: "test-sdk-version" });
21
- return {
22
- getAppVersion: vi.fn(() => "1.0.0"),
23
- getBundleId: vi.fn(() => "bundle-id"),
24
- getChannel: vi.fn(() => "production"),
25
- getActiveUpdateState: vi.fn<() => ActiveUpdateState>(),
26
- getCohort: vi.fn(() => "123"),
27
- getFingerprintHash: vi.fn(() => "fingerprint-hash"),
28
- getInstallId: vi.fn(() => "install-id"),
29
- getStorageItem: vi.fn<(key: string) => string | null>(() => null),
30
- setStorageItem: vi.fn(),
31
- readNotifyAppReady: vi.fn<
32
- () => {
33
- transition: LaunchTransition | null;
34
- pending: boolean;
35
- result: NotifyAppReadyResult;
36
- }
37
- >(() => createNotifyReadResult()),
38
- };
39
- });
40
-
41
- vi.mock("./native", () => mocks);
42
-
43
- const recordingPlugin = (
44
- hooks: (events: unknown[]) => HotUpdaterClientHooks = (events) => ({
45
- onAppReady: (result) => {
46
- events.push(["onAppReady", result]);
47
- },
48
- onBundleDownloaded: (info) => {
49
- events.push(["onBundleDownloaded", info]);
50
- },
51
- }),
52
- ) => {
53
- const events: unknown[] = [];
54
- const plugin: HotUpdaterClientPlugin = {
55
- id: "recorder",
56
- setup: () => hooks(events),
57
- };
58
- return { events, plugin };
59
- };
60
-
61
- const configure = async (
62
- plugins: HotUpdaterClientPlugin[],
63
- onError?: (error: unknown) => void,
64
- ) => {
65
- const { configurePlugins } = await import("./pluginHost");
66
- configurePlugins(plugins, {
67
- baseURL: "https://updates.example.com",
68
- ...(onError ? { onError } : {}),
69
- });
70
- };
71
-
72
- describe("app-ready reporting to plugins", () => {
73
- beforeEach(() => {
74
- vi.resetModules();
75
- vi.unstubAllGlobals();
76
- vi.useRealTimers();
77
- for (const mock of Object.values(mocks)) mock.mockReset();
78
- mocks.getAppVersion.mockReturnValue("1.0.0");
79
- mocks.getBundleId.mockReturnValue("bundle-id");
80
- mocks.getChannel.mockReturnValue("production");
81
- mocks.getActiveUpdateState.mockReturnValue({
82
- activeSelection: null,
83
- stableSelection: null,
84
- verificationPending: false,
85
- });
86
- mocks.getCohort.mockReturnValue("123");
87
- mocks.getFingerprintHash.mockReturnValue("fingerprint-hash");
88
- mocks.getInstallId.mockReturnValue("install-id");
89
- mocks.getStorageItem.mockReturnValue(null);
90
- mocks.readNotifyAppReady.mockReturnValue(createNotifyReadResult());
91
- });
92
-
93
- it.each([
94
- {
95
- label: "running selection",
96
- pending: false,
97
- channel: "production",
98
- expected: "release-running",
99
- },
100
- {
101
- label: "staged selection",
102
- pending: true,
103
- channel: "production",
104
- expected: "release-running",
105
- },
106
- {
107
- label: "another channel",
108
- pending: false,
109
- channel: "preview",
110
- expected: null,
111
- },
112
- ])(
113
- "attributes an unchanged launch with $label",
114
- async ({ pending, channel, expected }) => {
115
- stubNotifyFrame();
116
- const running = {
117
- kind: "BUNDLE" as const,
118
- releaseId: "release-running",
119
- bundleId: "bundle-id",
120
- channel,
121
- };
122
- mocks.getActiveUpdateState.mockReturnValue({
123
- activeSelection: pending
124
- ? {
125
- ...running,
126
- releaseId: "release-pending",
127
- bundleId: "bundle-pending",
128
- }
129
- : running,
130
- stableSelection: pending ? running : null,
131
- verificationPending: pending,
132
- });
133
- const { events, plugin } = recordingPlugin();
134
- await configure([plugin]);
135
- const { handleNotifyAppReady } = await import("./appReady");
136
-
137
- const readiness = handleNotifyAppReady({});
138
- await vi.runOnlyPendingTimersAsync();
139
- await readiness;
140
-
141
- expect(events).toEqual([
142
- [
143
- "onAppReady",
144
- {
145
- status: "UNCHANGED",
146
- channel: "production",
147
- bundleId: "bundle-id",
148
- releaseId: expected,
149
- previousProcessExit: null,
150
- } satisfies AppReadyResult,
151
- ],
152
- ]);
153
- },
154
- );
155
-
156
- it.each(["UPDATE_APPLIED", "RECOVERED"] as const)(
157
- "reports %s with the persisted transition and calls onNotifyAppReady",
158
- async (status) => {
159
- stubNotifyFrame();
160
- mocks.readNotifyAppReady.mockReturnValue(
161
- createNotifyReadResult(
162
- { status, fromBundleId: "bundle-a", toBundleId: "bundle-b" },
163
- {
164
- type: status,
165
- fromBundleId: "bundle-a",
166
- fromReleaseId: "release-a",
167
- toBundleId: "bundle-b",
168
- toReleaseId: "release-b",
169
- updateStrategy: "fingerprint",
170
- },
171
- ),
172
- );
173
- const { events, plugin } = recordingPlugin();
174
- await configure([plugin]);
175
- const onNotifyAppReady = vi.fn();
176
- const { handleNotifyAppReady } = await import("./appReady");
177
-
178
- const readiness = handleNotifyAppReady({ onNotifyAppReady });
179
- await vi.runOnlyPendingTimersAsync();
180
- await readiness;
181
-
182
- expect(events).toEqual([
183
- [
184
- "onAppReady",
185
- {
186
- status,
187
- channel: "production",
188
- fromBundleId: "bundle-a",
189
- fromReleaseId: "release-a",
190
- toBundleId: "bundle-b",
191
- toReleaseId: "release-b",
192
- updateStrategy: "fingerprint",
193
- previousProcessExit: null,
194
- },
195
- ],
196
- ]);
197
- expect(onNotifyAppReady).toHaveBeenCalledWith({
198
- status,
199
- fromBundleId: "bundle-a",
200
- toBundleId: "bundle-b",
201
- });
202
- },
203
- );
204
-
205
- it("waits for native launch verification before reporting", async () => {
206
- stubNotifyFrame();
207
- mocks.readNotifyAppReady
208
- .mockReturnValueOnce(createNotifyReadResult(undefined, null, true))
209
- .mockReturnValueOnce(createNotifyReadResult(undefined, null, true))
210
- .mockReturnValue(createNotifyReadResult());
211
- const { events, plugin } = recordingPlugin();
212
- await configure([plugin]);
213
- const { handleNotifyAppReady } = await import("./appReady");
214
-
215
- const readiness = handleNotifyAppReady({});
216
- await vi.runOnlyPendingTimersAsync();
217
- expect(events).toEqual([]);
218
- await vi.runAllTimersAsync();
219
- await readiness;
220
-
221
- expect(mocks.readNotifyAppReady).toHaveBeenCalledTimes(3);
222
- expect(events).toHaveLength(1);
223
- });
224
-
225
- it("reports the launch once per runtime while every init call gets readiness", async () => {
226
- stubNotifyFrame();
227
- const { events, plugin } = recordingPlugin();
228
- await configure([plugin]);
229
- const onNotifyAppReady = vi.fn();
230
- const { handleNotifyAppReady } = await import("./appReady");
231
-
232
- const first = handleNotifyAppReady({ onNotifyAppReady });
233
- const second = handleNotifyAppReady({ onNotifyAppReady });
234
- await vi.runOnlyPendingTimersAsync();
235
- await Promise.all([first, second]);
236
-
237
- expect(events).toHaveLength(1);
238
- expect(onNotifyAppReady).toHaveBeenCalledTimes(2);
239
- });
240
-
241
- it("skips onAppReady for an applied launch without its persisted transition", async () => {
242
- stubNotifyFrame();
243
- mocks.readNotifyAppReady.mockReturnValue(
244
- createNotifyReadResult(
245
- {
246
- status: "UPDATE_APPLIED",
247
- fromBundleId: "bundle-a",
248
- toBundleId: "bundle-b",
249
- },
250
- null,
251
- ),
252
- );
253
- const { events, plugin } = recordingPlugin();
254
- await configure([plugin]);
255
- const onNotifyAppReady = vi.fn();
256
- const { handleNotifyAppReady } = await import("./appReady");
257
-
258
- const readiness = handleNotifyAppReady({ onNotifyAppReady });
259
- await vi.runOnlyPendingTimersAsync();
260
- await readiness;
261
-
262
- expect(events).toEqual([]);
263
- expect(onNotifyAppReady).toHaveBeenCalledOnce();
264
- });
265
-
266
- it("reports a throwing or rejecting hook through onError and keeps readiness", async () => {
267
- stubNotifyFrame();
268
- const onError = vi.fn();
269
- const throwing: HotUpdaterClientPlugin = {
270
- id: "throwing",
271
- setup: () => ({
272
- onAppReady: () => {
273
- throw new Error("hook failed");
274
- },
275
- }),
276
- };
277
- const rejecting: HotUpdaterClientPlugin = {
278
- id: "rejecting",
279
- setup: () => ({
280
- onAppReady: async () => {
281
- throw new Error("hook rejected");
282
- },
283
- }),
284
- };
285
- await configure([throwing, rejecting], onError);
286
- const onNotifyAppReady = vi.fn();
287
- const { handleNotifyAppReady } = await import("./appReady");
288
-
289
- const readiness = handleNotifyAppReady({ onNotifyAppReady });
290
- await vi.runOnlyPendingTimersAsync();
291
- await readiness;
292
- await vi.runAllTimersAsync();
293
-
294
- expect(onNotifyAppReady).toHaveBeenCalledWith({ status: "UNCHANGED" });
295
- expect(onError).toHaveBeenCalledTimes(2);
296
- expect(onError).toHaveBeenCalledWith(
297
- expect.objectContaining({
298
- message: '[HotUpdater] Plugin "throwing" failed in onAppReady',
299
- cause: expect.objectContaining({ message: "hook failed" }),
300
- }),
301
- );
302
- expect(onError).toHaveBeenCalledWith(
303
- expect.objectContaining({
304
- message: '[HotUpdater] Plugin "rejecting" failed in onAppReady',
305
- }),
306
- );
307
- });
308
-
309
- it("delivers events after the launch, even when they happen first", async () => {
310
- stubNotifyFrame();
311
- const { events, plugin } = recordingPlugin();
312
- await configure([plugin]);
313
- const { emitAfterAppReady, handleNotifyAppReady } =
314
- await import("./appReady");
315
-
316
- const readiness = handleNotifyAppReady({});
317
- emitAfterAppReady("onBundleDownloaded", () => ({
318
- channel: "production",
319
- fromBundleId: "bundle-id",
320
- fromReleaseId: null,
321
- toBundleId: "next-bundle",
322
- toReleaseId: "next-release",
323
- updateStrategy: "appVersion",
324
- delivery: "manifest",
325
- patchFallback: false,
326
- }));
327
- expect(events).toEqual([]);
328
- await vi.runOnlyPendingTimersAsync();
329
- await readiness;
330
- await Promise.resolve();
331
-
332
- expect(events.map((event) => (event as [string])[0])).toEqual([
333
- "onAppReady",
334
- "onBundleDownloaded",
335
- ]);
336
- });
337
-
338
- it("passes on why the previous process exited, and keeps it for later events", async () => {
339
- stubNotifyFrame();
340
- mocks.readNotifyAppReady.mockReturnValue(
341
- createNotifyReadResult(
342
- {
343
- status: "RECOVERED",
344
- fromBundleId: "bundle-b",
345
- toBundleId: "bundle-a",
346
- },
347
- {
348
- type: "RECOVERED",
349
- fromBundleId: "bundle-b",
350
- fromReleaseId: null,
351
- toBundleId: "bundle-a",
352
- toReleaseId: null,
353
- updateStrategy: "appVersion",
354
- },
355
- false,
356
- "CRASH_NATIVE",
357
- ),
358
- );
359
- const { events, plugin } = recordingPlugin();
360
- await configure([plugin]);
361
- const { getPreviousProcessExit, handleNotifyAppReady } =
362
- await import("./appReady");
363
- expect(getPreviousProcessExit()).toBeNull();
364
-
365
- const readiness = handleNotifyAppReady({});
366
- await vi.runOnlyPendingTimersAsync();
367
- await readiness;
368
-
369
- expect(events).toEqual([
370
- [
371
- "onAppReady",
372
- expect.objectContaining({
373
- status: "RECOVERED",
374
- previousProcessExit: "CRASH_NATIVE",
375
- }),
376
- ],
377
- ]);
378
- expect(getPreviousProcessExit()).toBe("CRASH_NATIVE");
379
- });
380
-
381
- it("builds no event when no plugin listens", async () => {
382
- stubNotifyFrame();
383
- await configure([]);
384
- const { handleNotifyAppReady } = await import("./appReady");
385
-
386
- const readiness = handleNotifyAppReady({});
387
- await vi.runOnlyPendingTimersAsync();
388
- await readiness;
389
-
390
- expect(mocks.getActiveUpdateState).not.toHaveBeenCalled();
391
- expect(mocks.getBundleId).not.toHaveBeenCalled();
392
- });
393
- });
@@ -1,31 +0,0 @@
1
- import { vi } from "vitest";
2
-
3
- import type { LaunchTransition, NotifyAppReadyResult } from "./native";
4
-
5
- export const createNotifyReadResult = (
6
- result: NotifyAppReadyResult = { status: "UNCHANGED" },
7
- transition: LaunchTransition | null = null,
8
- pending = false,
9
- previousProcessExit: string | null = null,
10
- ): {
11
- transition: LaunchTransition | null;
12
- previousProcessExit: string | null;
13
- pending: boolean;
14
- result: NotifyAppReadyResult;
15
- } => ({
16
- transition,
17
- previousProcessExit,
18
- pending,
19
- result,
20
- });
21
-
22
- export const stubNotifyFrame = () => {
23
- vi.useFakeTimers();
24
- vi.stubGlobal(
25
- "requestAnimationFrame",
26
- vi.fn((callback: (timestamp: number) => void) => {
27
- setTimeout(() => callback(0), 0);
28
- return 1;
29
- }),
30
- );
31
- };
package/src/baseURL.ts DELETED
@@ -1,15 +0,0 @@
1
- import type { HotUpdaterBaseURL } from "./types";
2
-
3
- /** Resolves a functional baseURL and drops trailing slashes. */
4
- export const resolveBaseURL = async (
5
- baseURL: HotUpdaterBaseURL,
6
- ): Promise<string> => {
7
- const resolvedBaseURL =
8
- typeof baseURL === "function" ? await baseURL() : baseURL;
9
-
10
- if (!resolvedBaseURL) {
11
- throw new Error("baseURL function must return a non-empty string");
12
- }
13
-
14
- return resolvedBaseURL.replace(/\/+$/, "");
15
- };
@@ -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
- });