@hot-updater/react-native 1.0.0-rc.1 → 1.0.0-rc.3

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 (122) hide show
  1. package/android/src/main/java/com/hotupdater/BundleFileStorageService.kt +1 -1
  2. package/lib/commonjs/checkForUpdate.js +4 -4
  3. package/lib/commonjs/checkForUpdate.js.map +1 -1
  4. package/lib/commonjs/checkForUpdate.releaseCatalog.spec.js +34 -23
  5. package/lib/commonjs/checkForUpdate.releaseCatalog.spec.js.map +1 -1
  6. package/lib/commonjs/httpClient.js +2 -2
  7. package/lib/commonjs/httpClient.js.map +1 -1
  8. package/lib/commonjs/index.js +8 -6
  9. package/lib/commonjs/index.js.map +1 -1
  10. package/lib/commonjs/index.spec.js +49 -11
  11. package/lib/commonjs/index.spec.js.map +1 -1
  12. package/lib/commonjs/native.js +8 -6
  13. package/lib/commonjs/native.js.map +1 -1
  14. package/lib/commonjs/native.spec.js +107 -6
  15. package/lib/commonjs/native.spec.js.map +1 -1
  16. package/lib/commonjs/{notifyAppReadyAnalytics.boundary.spec.js → notifyAppReadyInsights.boundary.spec.js} +21 -21
  17. package/lib/commonjs/notifyAppReadyInsights.boundary.spec.js.map +1 -0
  18. package/lib/commonjs/{notifyAppReadyAnalytics.js → notifyAppReadyInsights.js} +27 -27
  19. package/lib/commonjs/notifyAppReadyInsights.js.map +1 -0
  20. package/lib/commonjs/{notifyAppReadyAnalytics.spec.js → notifyAppReadyInsights.spec.js} +29 -29
  21. package/lib/commonjs/notifyAppReadyInsights.spec.js.map +1 -0
  22. package/lib/commonjs/{notifyAppReadyAnalytics.test-utils.js → notifyAppReadyInsights.test-utils.js} +3 -3
  23. package/lib/commonjs/notifyAppReadyInsights.test-utils.js.map +1 -0
  24. package/lib/commonjs/{notifyAppReadyAnalytics.transport.spec.js → notifyAppReadyInsights.transport.spec.js} +7 -7
  25. package/lib/commonjs/notifyAppReadyInsights.transport.spec.js.map +1 -0
  26. package/lib/commonjs/sdkVersion.js +1 -1
  27. package/lib/commonjs/wrap.js +5 -5
  28. package/lib/commonjs/wrap.js.map +1 -1
  29. package/lib/commonjs/wrap.spec.js +58 -25
  30. package/lib/commonjs/wrap.spec.js.map +1 -1
  31. package/lib/module/checkForUpdate.js +4 -4
  32. package/lib/module/checkForUpdate.js.map +1 -1
  33. package/lib/module/checkForUpdate.releaseCatalog.spec.js +34 -23
  34. package/lib/module/checkForUpdate.releaseCatalog.spec.js.map +1 -1
  35. package/lib/module/httpClient.js +2 -2
  36. package/lib/module/httpClient.js.map +1 -1
  37. package/lib/module/index.js +9 -7
  38. package/lib/module/index.js.map +1 -1
  39. package/lib/module/index.spec.js +49 -11
  40. package/lib/module/index.spec.js.map +1 -1
  41. package/lib/module/native.js +6 -4
  42. package/lib/module/native.js.map +1 -1
  43. package/lib/module/native.spec.js +107 -6
  44. package/lib/module/native.spec.js.map +1 -1
  45. package/lib/module/{notifyAppReadyAnalytics.boundary.spec.js → notifyAppReadyInsights.boundary.spec.js} +16 -16
  46. package/lib/module/notifyAppReadyInsights.boundary.spec.js.map +1 -0
  47. package/lib/module/{notifyAppReadyAnalytics.js → notifyAppReadyInsights.js} +27 -27
  48. package/lib/module/notifyAppReadyInsights.js.map +1 -0
  49. package/lib/module/{notifyAppReadyAnalytics.spec.js → notifyAppReadyInsights.spec.js} +21 -21
  50. package/lib/module/notifyAppReadyInsights.spec.js.map +1 -0
  51. package/lib/module/{notifyAppReadyAnalytics.test-utils.js → notifyAppReadyInsights.test-utils.js} +3 -3
  52. package/lib/module/notifyAppReadyInsights.test-utils.js.map +1 -0
  53. package/lib/module/{notifyAppReadyAnalytics.transport.spec.js → notifyAppReadyInsights.transport.spec.js} +4 -4
  54. package/lib/module/notifyAppReadyInsights.transport.spec.js.map +1 -0
  55. package/lib/module/sdkVersion.js +1 -1
  56. package/lib/module/wrap.js +4 -4
  57. package/lib/module/wrap.js.map +1 -1
  58. package/lib/module/wrap.spec.js +60 -25
  59. package/lib/module/wrap.spec.js.map +1 -1
  60. package/lib/typescript/commonjs/checkForUpdate.d.ts +1 -1
  61. package/lib/typescript/commonjs/checkForUpdate.d.ts.map +1 -1
  62. package/lib/typescript/commonjs/httpClient.d.ts +5 -5
  63. package/lib/typescript/commonjs/httpClient.d.ts.map +1 -1
  64. package/lib/typescript/commonjs/index.d.ts +4 -5
  65. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  66. package/lib/typescript/commonjs/native.d.ts +4 -3
  67. package/lib/typescript/commonjs/native.d.ts.map +1 -1
  68. package/lib/typescript/{module/notifyAppReadyAnalytics.d.ts → commonjs/notifyAppReadyInsights.d.ts} +2 -2
  69. package/lib/typescript/commonjs/notifyAppReadyInsights.d.ts.map +1 -0
  70. package/lib/typescript/commonjs/notifyAppReadyInsights.test-utils.d.ts +8 -0
  71. package/lib/typescript/commonjs/notifyAppReadyInsights.test-utils.d.ts.map +1 -0
  72. package/lib/typescript/commonjs/sdkVersion.d.ts +1 -1
  73. package/lib/typescript/commonjs/wrap.types.d.ts +5 -6
  74. package/lib/typescript/commonjs/wrap.types.d.ts.map +1 -1
  75. package/lib/typescript/module/checkForUpdate.d.ts +1 -1
  76. package/lib/typescript/module/checkForUpdate.d.ts.map +1 -1
  77. package/lib/typescript/module/httpClient.d.ts +5 -5
  78. package/lib/typescript/module/httpClient.d.ts.map +1 -1
  79. package/lib/typescript/module/index.d.ts +4 -5
  80. package/lib/typescript/module/index.d.ts.map +1 -1
  81. package/lib/typescript/module/native.d.ts +4 -3
  82. package/lib/typescript/module/native.d.ts.map +1 -1
  83. package/lib/typescript/{commonjs/notifyAppReadyAnalytics.d.ts → module/notifyAppReadyInsights.d.ts} +2 -2
  84. package/lib/typescript/module/notifyAppReadyInsights.d.ts.map +1 -0
  85. package/lib/typescript/module/notifyAppReadyInsights.test-utils.d.ts +8 -0
  86. package/lib/typescript/module/notifyAppReadyInsights.test-utils.d.ts.map +1 -0
  87. package/lib/typescript/module/sdkVersion.d.ts +1 -1
  88. package/lib/typescript/module/wrap.types.d.ts +5 -6
  89. package/lib/typescript/module/wrap.types.d.ts.map +1 -1
  90. package/package.json +2 -2
  91. package/src/checkForUpdate.releaseCatalog.spec.ts +71 -56
  92. package/src/checkForUpdate.ts +5 -9
  93. package/src/httpClient.ts +10 -10
  94. package/src/index.spec.ts +55 -11
  95. package/src/index.ts +10 -10
  96. package/src/native.spec.ts +110 -6
  97. package/src/native.ts +9 -8
  98. package/src/{notifyAppReadyAnalytics.boundary.spec.ts → notifyAppReadyInsights.boundary.spec.ts} +17 -17
  99. package/src/{notifyAppReadyAnalytics.spec.ts → notifyAppReadyInsights.spec.ts} +22 -22
  100. package/src/{notifyAppReadyAnalytics.test-utils.ts → notifyAppReadyInsights.test-utils.ts} +4 -4
  101. package/src/{notifyAppReadyAnalytics.transport.spec.ts → notifyAppReadyInsights.transport.spec.ts} +5 -5
  102. package/src/{notifyAppReadyAnalytics.ts → notifyAppReadyInsights.ts} +33 -33
  103. package/src/sdkVersion.ts +1 -1
  104. package/src/wrap.spec.ts +70 -31
  105. package/src/wrap.tsx +4 -4
  106. package/src/wrap.types.ts +5 -6
  107. package/lib/commonjs/notifyAppReadyAnalytics.boundary.spec.js.map +0 -1
  108. package/lib/commonjs/notifyAppReadyAnalytics.js.map +0 -1
  109. package/lib/commonjs/notifyAppReadyAnalytics.spec.js.map +0 -1
  110. package/lib/commonjs/notifyAppReadyAnalytics.test-utils.js.map +0 -1
  111. package/lib/commonjs/notifyAppReadyAnalytics.transport.spec.js.map +0 -1
  112. package/lib/module/notifyAppReadyAnalytics.boundary.spec.js.map +0 -1
  113. package/lib/module/notifyAppReadyAnalytics.js.map +0 -1
  114. package/lib/module/notifyAppReadyAnalytics.spec.js.map +0 -1
  115. package/lib/module/notifyAppReadyAnalytics.test-utils.js.map +0 -1
  116. package/lib/module/notifyAppReadyAnalytics.transport.spec.js.map +0 -1
  117. package/lib/typescript/commonjs/notifyAppReadyAnalytics.d.ts.map +0 -1
  118. package/lib/typescript/commonjs/notifyAppReadyAnalytics.test-utils.d.ts +0 -8
  119. package/lib/typescript/commonjs/notifyAppReadyAnalytics.test-utils.d.ts.map +0 -1
  120. package/lib/typescript/module/notifyAppReadyAnalytics.d.ts.map +0 -1
  121. package/lib/typescript/module/notifyAppReadyAnalytics.test-utils.d.ts +0 -8
  122. package/lib/typescript/module/notifyAppReadyAnalytics.test-utils.d.ts.map +0 -1
@@ -1,13 +1,13 @@
1
1
  import { beforeEach, describe, expect, it, vi } from "vitest";
2
2
 
3
3
  import type {
4
- NotifyAppReadyAnalyticsEvent,
4
+ NotifyAppReadyInsightsEvent,
5
5
  NotifyAppReadyResult,
6
6
  } from "./native";
7
7
  import {
8
8
  createNotifyReadResult,
9
9
  stubNotifyFrame,
10
- } from "./notifyAppReadyAnalytics.test-utils";
10
+ } from "./notifyAppReadyInsights.test-utils";
11
11
 
12
12
  vi.mock("react-native", () => ({
13
13
  Platform: { OS: "ios" },
@@ -25,7 +25,7 @@ const mocks = vi.hoisted(() => ({
25
25
  getPersistedUserIdentity: vi.fn(() => ({})),
26
26
  readNotifyAppReady: vi.fn<
27
27
  () => {
28
- analyticsEvent: NotifyAppReadyAnalyticsEvent | null;
28
+ insightsEvent: NotifyAppReadyInsightsEvent | null;
29
29
  pending: boolean;
30
30
  result: NotifyAppReadyResult;
31
31
  }
@@ -51,20 +51,20 @@ vi.mock("./native", () => ({
51
51
  }));
52
52
 
53
53
  const createClient = () => {
54
- const sendAnalyticsEvent = vi.fn().mockResolvedValue(undefined);
54
+ const sendInsightsEvent = vi.fn().mockResolvedValue(undefined);
55
55
  return {
56
56
  client: {
57
57
  createSession: vi.fn(async () => ({
58
58
  fetchReleaseCatalog: vi.fn(),
59
59
  resolveArtifact: vi.fn(),
60
- sendAnalyticsEvent,
60
+ sendInsightsEvent,
61
61
  })),
62
62
  },
63
- sendAnalyticsEvent,
63
+ sendInsightsEvent,
64
64
  };
65
65
  };
66
66
 
67
- describe("automatic notifyAppReady analytics", () => {
67
+ describe("automatic notifyAppReady insights", () => {
68
68
  beforeEach(() => {
69
69
  vi.resetModules();
70
70
  vi.unstubAllGlobals();
@@ -107,12 +107,12 @@ describe("automatic notifyAppReady analytics", () => {
107
107
  ),
108
108
  );
109
109
 
110
- const { client, sendAnalyticsEvent } = createClient();
110
+ const { client, sendInsightsEvent } = createClient();
111
111
  const onNotifyAppReady = vi.fn();
112
112
  const { init } = await import("./wrap");
113
113
 
114
114
  init({
115
- analytics: true,
115
+ insights: true,
116
116
  onNotifyAppReady,
117
117
  requestHeaders: { Authorization: "Bearer token" },
118
118
  requestTimeout: 1000,
@@ -120,7 +120,7 @@ describe("automatic notifyAppReady analytics", () => {
120
120
  });
121
121
  await vi.runOnlyPendingTimersAsync();
122
122
 
123
- expect(sendAnalyticsEvent).toHaveBeenCalledWith({
123
+ expect(sendInsightsEvent).toHaveBeenCalledWith({
124
124
  appVersion: "1.0.0",
125
125
  channel: "production",
126
126
  cohort: "123",
@@ -162,14 +162,14 @@ describe("automatic notifyAppReady analytics", () => {
162
162
  },
163
163
  ),
164
164
  );
165
- const { client, sendAnalyticsEvent } = createClient();
165
+ const { client, sendInsightsEvent } = createClient();
166
166
  const onNotifyAppReady = vi.fn();
167
167
  const { init } = await import("./wrap");
168
168
 
169
- init({ analytics: true, client, onNotifyAppReady });
169
+ init({ insights: true, client, onNotifyAppReady });
170
170
  await vi.runOnlyPendingTimersAsync();
171
171
 
172
- expect(sendAnalyticsEvent).toHaveBeenCalledWith({
172
+ expect(sendInsightsEvent).toHaveBeenCalledWith({
173
173
  appVersion: "1.0.0",
174
174
  channel: "production",
175
175
  cohort: "123",
@@ -194,16 +194,16 @@ describe("automatic notifyAppReady analytics", () => {
194
194
 
195
195
  it("sends one UNCHANGED event for repeated init calls", async () => {
196
196
  stubNotifyFrame();
197
- const { client, sendAnalyticsEvent } = createClient();
197
+ const { client, sendInsightsEvent } = createClient();
198
198
  const onNotifyAppReady = vi.fn();
199
199
  const { init } = await import("./wrap");
200
200
 
201
- init({ analytics: true, client, onNotifyAppReady });
202
- init({ analytics: true, client, onNotifyAppReady });
201
+ init({ insights: true, client, onNotifyAppReady });
202
+ init({ insights: true, client, onNotifyAppReady });
203
203
  await vi.runOnlyPendingTimersAsync();
204
204
 
205
- expect(sendAnalyticsEvent).toHaveBeenCalledTimes(1);
206
- expect(sendAnalyticsEvent).toHaveBeenCalledWith({
205
+ expect(sendInsightsEvent).toHaveBeenCalledTimes(1);
206
+ expect(sendInsightsEvent).toHaveBeenCalledWith({
207
207
  appVersion: "1.0.0",
208
208
  channel: "production",
209
209
  cohort: "123",
@@ -228,16 +228,16 @@ describe("automatic notifyAppReady analytics", () => {
228
228
  });
229
229
  });
230
230
 
231
- it("skips automatic analytics when disabled while preserving readiness", async () => {
231
+ it("skips automatic insights when disabled while preserving readiness", async () => {
232
232
  stubNotifyFrame();
233
- const { client, sendAnalyticsEvent } = createClient();
233
+ const { client, sendInsightsEvent } = createClient();
234
234
  const onNotifyAppReady = vi.fn();
235
235
  const { init } = await import("./wrap");
236
236
 
237
- init({ analytics: false, client, onNotifyAppReady });
237
+ init({ insights: false, client, onNotifyAppReady });
238
238
  await vi.runOnlyPendingTimersAsync();
239
239
 
240
- expect(sendAnalyticsEvent).not.toHaveBeenCalled();
240
+ expect(sendInsightsEvent).not.toHaveBeenCalled();
241
241
  expect(onNotifyAppReady).toHaveBeenCalledWith({ status: "UNCHANGED" });
242
242
  });
243
243
  });
@@ -1,20 +1,20 @@
1
1
  import { vi } from "vitest";
2
2
 
3
3
  import type {
4
- NotifyAppReadyAnalyticsEvent,
4
+ NotifyAppReadyInsightsEvent,
5
5
  NotifyAppReadyResult,
6
6
  } from "./native";
7
7
 
8
8
  export const createNotifyReadResult = (
9
9
  result: NotifyAppReadyResult = { status: "UNCHANGED" },
10
- analyticsEvent: NotifyAppReadyAnalyticsEvent | null = null,
10
+ insightsEvent: NotifyAppReadyInsightsEvent | null = null,
11
11
  pending = false,
12
12
  ): {
13
- analyticsEvent: NotifyAppReadyAnalyticsEvent | null;
13
+ insightsEvent: NotifyAppReadyInsightsEvent | null;
14
14
  pending: boolean;
15
15
  result: NotifyAppReadyResult;
16
16
  } => ({
17
- analyticsEvent,
17
+ insightsEvent,
18
18
  pending,
19
19
  result,
20
20
  });
@@ -1,13 +1,13 @@
1
1
  import { beforeEach, describe, expect, it, vi } from "vitest";
2
2
 
3
3
  import type {
4
- NotifyAppReadyAnalyticsEvent,
4
+ NotifyAppReadyInsightsEvent,
5
5
  NotifyAppReadyResult,
6
6
  } from "./native";
7
7
  import {
8
8
  createNotifyReadResult,
9
9
  stubNotifyFrame,
10
- } from "./notifyAppReadyAnalytics.test-utils";
10
+ } from "./notifyAppReadyInsights.test-utils";
11
11
 
12
12
  vi.mock("react-native", () => ({
13
13
  Platform: { OS: "ios" },
@@ -36,7 +36,7 @@ const mocks = vi.hoisted(() => ({
36
36
  getPersistedUserIdentity: vi.fn(() => ({})),
37
37
  readNotifyAppReady: vi.fn<
38
38
  () => {
39
- analyticsEvent: NotifyAppReadyAnalyticsEvent | null;
39
+ insightsEvent: NotifyAppReadyInsightsEvent | null;
40
40
  pending: boolean;
41
41
  result: NotifyAppReadyResult;
42
42
  }
@@ -110,7 +110,7 @@ describe("automatic notifyAppReady transport failures", () => {
110
110
  "https://updates.example.test/hot-updater",
111
111
  );
112
112
 
113
- init({ analytics: true, client, onError, onNotifyAppReady });
113
+ init({ insights: true, client, onError, onNotifyAppReady });
114
114
  await vi.runOnlyPendingTimersAsync();
115
115
 
116
116
  expect(fetchMock).toHaveBeenCalledTimes(1);
@@ -119,7 +119,7 @@ describe("automatic notifyAppReady transport failures", () => {
119
119
  status: "UNCHANGED",
120
120
  });
121
121
  expect(warn).toHaveBeenCalledWith(
122
- "[HotUpdater] Automatic notifyAppReady analytics failed:",
122
+ "[HotUpdater] Automatic notifyAppReady insights failed:",
123
123
  expect.any(Error),
124
124
  );
125
125
  } finally {
@@ -1,7 +1,7 @@
1
1
  import { Platform } from "react-native";
2
2
 
3
3
  import type { HotUpdaterError } from "./error";
4
- import type { AnalyticsEventParams, HotUpdaterHttpClient } from "./httpClient";
4
+ import type { InsightsEventParams, HotUpdaterHttpClient } from "./httpClient";
5
5
  import {
6
6
  getAppVersion,
7
7
  getBundleId,
@@ -10,13 +10,13 @@ import {
10
10
  getFingerprintHash,
11
11
  getInstallId,
12
12
  getPersistedUserIdentity,
13
- type NotifyAppReadyAnalyticsEvent,
13
+ type NotifyAppReadyInsightsEvent,
14
14
  type NotifyAppReadyResult,
15
15
  readNotifyAppReady,
16
16
  } from "./native";
17
17
 
18
18
  export type NotifyAppReadyOptions = {
19
- analytics?: boolean;
19
+ insights?: boolean;
20
20
  client: HotUpdaterHttpClient;
21
21
  requestHeaders?: Record<string, string>;
22
22
  requestTimeout?: number;
@@ -26,7 +26,7 @@ export type NotifyAppReadyOptions = {
26
26
 
27
27
  type RequestAnimationFrame = (callback: (timestamp: number) => void) => number;
28
28
 
29
- let didAttemptAutomaticAnalytics = false;
29
+ let didAttemptAutomaticInsights = false;
30
30
 
31
31
  const waitForNextFrame = () =>
32
32
  new Promise<void>((resolve) => {
@@ -48,16 +48,16 @@ const assertNever = (value: never): never => {
48
48
  throw new Error(`[HotUpdater] Unexpected notifyAppReady status: ${value}`);
49
49
  };
50
50
 
51
- const buildNotifyAppReadyAnalyticsParams = (
51
+ const buildNotifyAppReadyInsightsParams = (
52
52
  nativeResult: NotifyAppReadyResult,
53
- analyticsEvent: NotifyAppReadyAnalyticsEvent | null,
53
+ insightsEvent: NotifyAppReadyInsightsEvent | null,
54
54
  options: Pick<NotifyAppReadyOptions, "requestHeaders" | "requestTimeout">,
55
- ): AnalyticsEventParams => {
55
+ ): InsightsEventParams => {
56
56
  const appVersion = getAppVersion();
57
57
 
58
58
  if (!appVersion) {
59
59
  throw new Error(
60
- "[HotUpdater] Automatic analytics requires a non-null native app version.",
60
+ "[HotUpdater] Automatic insights requires a non-null native app version.",
61
61
  );
62
62
  }
63
63
 
@@ -66,7 +66,7 @@ const buildNotifyAppReadyAnalyticsParams = (
66
66
 
67
67
  if (!installId) {
68
68
  throw new Error(
69
- "[HotUpdater] Automatic analytics requires a non-null native install id.",
69
+ "[HotUpdater] Automatic insights requires a non-null native install id.",
70
70
  );
71
71
  }
72
72
 
@@ -78,12 +78,12 @@ const buildNotifyAppReadyAnalyticsParams = (
78
78
  channel: getChannel(),
79
79
  cohort: getCohort(),
80
80
  fingerprintHash: getFingerprintHash(),
81
- fromReleaseId: analyticsEvent?.fromReleaseId ?? null,
81
+ fromReleaseId: insightsEvent?.fromReleaseId ?? null,
82
82
  installId,
83
83
  platform,
84
84
  requestHeaders: options.requestHeaders,
85
85
  requestTimeout: options.requestTimeout,
86
- toReleaseId: analyticsEvent?.toReleaseId ?? null,
86
+ toReleaseId: insightsEvent?.toReleaseId ?? null,
87
87
  ...(userId != null ? { userId } : {}),
88
88
  ...(username != null ? { username } : {}),
89
89
  };
@@ -94,7 +94,7 @@ const buildNotifyAppReadyAnalyticsParams = (
94
94
 
95
95
  if (!bundleId) {
96
96
  throw new Error(
97
- "[HotUpdater] Automatic analytics requires a non-null current bundle id.",
97
+ "[HotUpdater] Automatic insights requires a non-null current bundle id.",
98
98
  );
99
99
  }
100
100
 
@@ -108,57 +108,57 @@ const buildNotifyAppReadyAnalyticsParams = (
108
108
  }
109
109
  case "UPDATE_APPLIED":
110
110
  case "RECOVERED":
111
- if (!analyticsEvent) {
111
+ if (!insightsEvent) {
112
112
  throw new Error(
113
- "[HotUpdater] Native launch report is missing persisted metadata required for automatic analytics.",
113
+ "[HotUpdater] Native launch report is missing persisted metadata required for automatic insights.",
114
114
  );
115
115
  }
116
116
 
117
- switch (analyticsEvent.type) {
117
+ switch (insightsEvent.type) {
118
118
  case "UPDATE_APPLIED":
119
119
  return {
120
120
  ...commonParams,
121
- fromBundleId: analyticsEvent.fromBundleId,
122
- toBundleId: analyticsEvent.toBundleId,
121
+ fromBundleId: insightsEvent.fromBundleId,
122
+ toBundleId: insightsEvent.toBundleId,
123
123
  type: "UPDATE_APPLIED",
124
- updateStrategy: analyticsEvent.updateStrategy,
124
+ updateStrategy: insightsEvent.updateStrategy,
125
125
  };
126
126
  case "RECOVERED":
127
127
  return {
128
128
  ...commonParams,
129
- fromBundleId: analyticsEvent.fromBundleId,
130
- toBundleId: analyticsEvent.toBundleId,
129
+ fromBundleId: insightsEvent.fromBundleId,
130
+ toBundleId: insightsEvent.toBundleId,
131
131
  type: "RECOVERED",
132
- updateStrategy: analyticsEvent.updateStrategy,
132
+ updateStrategy: insightsEvent.updateStrategy,
133
133
  };
134
134
  default:
135
- return assertNever(analyticsEvent.type);
135
+ return assertNever(insightsEvent.type);
136
136
  }
137
137
  default:
138
138
  return assertNever(nativeResult);
139
139
  }
140
140
  };
141
141
 
142
- const maybeSendAutomaticAnalytics = async (
142
+ const maybeSendAutomaticInsights = async (
143
143
  options: NotifyAppReadyOptions,
144
144
  nativeResult: NotifyAppReadyResult,
145
- analyticsEvent: NotifyAppReadyAnalyticsEvent | null,
145
+ insightsEvent: NotifyAppReadyInsightsEvent | null,
146
146
  ): Promise<void> => {
147
- if (!options.analytics || didAttemptAutomaticAnalytics) {
147
+ if (!options.insights || didAttemptAutomaticInsights) {
148
148
  return;
149
149
  }
150
150
 
151
- didAttemptAutomaticAnalytics = true;
151
+ didAttemptAutomaticInsights = true;
152
152
 
153
- if (nativeResult.status !== "UNCHANGED" && !analyticsEvent) {
153
+ if (nativeResult.status !== "UNCHANGED" && !insightsEvent) {
154
154
  throw new Error(
155
- "[HotUpdater] Native launch report is missing persisted metadata required for automatic analytics.",
155
+ "[HotUpdater] Native launch report is missing persisted metadata required for automatic insights.",
156
156
  );
157
157
  }
158
158
 
159
159
  const session = await options.client.createSession();
160
- await session.sendAnalyticsEvent(
161
- buildNotifyAppReadyAnalyticsParams(nativeResult, analyticsEvent, options),
160
+ await session.sendInsightsEvent(
161
+ buildNotifyAppReadyInsightsParams(nativeResult, insightsEvent, options),
162
162
  );
163
163
  };
164
164
 
@@ -172,14 +172,14 @@ export const handleNotifyAppReady = async (
172
172
  nativeReadResult = readNotifyAppReady();
173
173
  } while (nativeReadResult.pending);
174
174
 
175
- const { analyticsEvent, result: nativeResult } = nativeReadResult;
175
+ const { insightsEvent, result: nativeResult } = nativeReadResult;
176
176
 
177
177
  try {
178
- await maybeSendAutomaticAnalytics(options, nativeResult, analyticsEvent);
178
+ await maybeSendAutomaticInsights(options, nativeResult, insightsEvent);
179
179
  } catch (error) {
180
180
  const warning = error instanceof Error ? error : new Error(String(error));
181
181
  console.warn(
182
- "[HotUpdater] Automatic notifyAppReady analytics failed:",
182
+ "[HotUpdater] Automatic notifyAppReady insights failed:",
183
183
  warning,
184
184
  );
185
185
  }
package/src/sdkVersion.ts CHANGED
@@ -1 +1 @@
1
- export const HOT_UPDATER_SDK_VERSION = "1.0.0-rc.1";
1
+ export const HOT_UPDATER_SDK_VERSION = "1.0.0-rc.3";
package/src/wrap.spec.ts CHANGED
@@ -1,8 +1,11 @@
1
- import type React from "react";
2
- import { beforeEach, describe, expect, it, vi } from "vitest";
1
+ // @vitest-environment jsdom
2
+
3
+ import { cleanup, render, waitFor } from "@testing-library/react";
4
+ import { createElement, type ComponentType } from "react";
5
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
3
6
 
4
7
  import type {
5
- NotifyAppReadyAnalyticsEvent,
8
+ NotifyAppReadyInsightsEvent,
6
9
  NotifyAppReadyResult,
7
10
  } from "./native";
8
11
  import type { HotUpdaterOptions } from "./wrap";
@@ -15,14 +18,14 @@ vi.mock("react-native", () => ({
15
18
 
16
19
  const createNotifyReadResult = (
17
20
  result: NotifyAppReadyResult = { status: "UNCHANGED" },
18
- analyticsEvent: NotifyAppReadyAnalyticsEvent | null = null,
21
+ insightsEvent: NotifyAppReadyInsightsEvent | null = null,
19
22
  pending = false,
20
23
  ): {
21
- analyticsEvent: NotifyAppReadyAnalyticsEvent | null;
24
+ insightsEvent: NotifyAppReadyInsightsEvent | null;
22
25
  pending: boolean;
23
26
  result: NotifyAppReadyResult;
24
27
  } => ({
25
- analyticsEvent,
28
+ insightsEvent,
26
29
  pending,
27
30
  result,
28
31
  });
@@ -32,6 +35,7 @@ const mocks = vi.hoisted(() => ({
32
35
  checkForUpdate: vi.fn(),
33
36
  getAppVersion: vi.fn(() => "1.0.0"),
34
37
  getBundleId: vi.fn(() => "bundle-id"),
38
+ getUpdateId: vi.fn(() => "release-id"),
35
39
  getChannel: vi.fn(() => "production"),
36
40
  getCohort: vi.fn(() => "123"),
37
41
  getFingerprintHash: vi.fn(() => "fingerprint-hash"),
@@ -39,7 +43,7 @@ const mocks = vi.hoisted(() => ({
39
43
  getPersistedUserIdentity: vi.fn(() => ({})),
40
44
  readNotifyAppReady: vi.fn<
41
45
  () => {
42
- analyticsEvent: NotifyAppReadyAnalyticsEvent | null;
46
+ insightsEvent: NotifyAppReadyInsightsEvent | null;
43
47
  pending: boolean;
44
48
  result: NotifyAppReadyResult;
45
49
  }
@@ -55,6 +59,7 @@ vi.mock("./native", () => ({
55
59
  addListener: mocks.addListener,
56
60
  getAppVersion: mocks.getAppVersion,
57
61
  getBundleId: mocks.getBundleId,
62
+ getUpdateId: mocks.getUpdateId,
58
63
  getChannel: mocks.getChannel,
59
64
  getCohort: mocks.getCohort,
60
65
  getFingerprintHash: mocks.getFingerprintHash,
@@ -65,16 +70,16 @@ vi.mock("./native", () => ({
65
70
  }));
66
71
 
67
72
  const createClient = (
68
- sendAnalyticsEvent = vi.fn().mockResolvedValue(undefined),
73
+ sendInsightsEvent = vi.fn().mockResolvedValue(undefined),
69
74
  ) => ({
70
75
  client: {
71
76
  createSession: vi.fn(async () => ({
72
77
  fetchReleaseCatalog: vi.fn(),
73
78
  resolveArtifact: vi.fn(),
74
- sendAnalyticsEvent,
79
+ sendInsightsEvent,
75
80
  })),
76
81
  },
77
- sendAnalyticsEvent,
82
+ sendInsightsEvent,
78
83
  });
79
84
 
80
85
  describe("HotUpdater wrap initialization", () => {
@@ -92,6 +97,7 @@ describe("HotUpdater wrap initialization", () => {
92
97
  mocks.getAppVersion.mockReturnValue("1.0.0");
93
98
  mocks.getPersistedUserIdentity.mockReturnValue({});
94
99
  mocks.getBundleId.mockReturnValue("bundle-id");
100
+ mocks.getUpdateId.mockReturnValue("release-id");
95
101
  mocks.getChannel.mockReturnValue("production");
96
102
  mocks.getCohort.mockReturnValue("123");
97
103
  mocks.getFingerprintHash.mockReturnValue("fingerprint-hash");
@@ -99,6 +105,39 @@ describe("HotUpdater wrap initialization", () => {
99
105
  mocks.readNotifyAppReady.mockReturnValue(createNotifyReadResult());
100
106
  });
101
107
 
108
+ afterEach(cleanup);
109
+
110
+ it("reports the console ID when up to date while retaining file IDs in insights", async () => {
111
+ const onUpdateProcessCompleted = vi.fn();
112
+ const { client, sendInsightsEvent } = createClient();
113
+ const { wrap } = await import("./wrap");
114
+ const WrappedComponent = wrap({
115
+ insights: true,
116
+ client,
117
+ onUpdateProcessCompleted,
118
+ updateStrategy: "appVersion",
119
+ })(() => null);
120
+
121
+ render(createElement(WrappedComponent));
122
+
123
+ await waitFor(() =>
124
+ expect(onUpdateProcessCompleted).toHaveBeenCalledWith({
125
+ id: "release-id",
126
+ message: null,
127
+ shouldForceUpdate: false,
128
+ status: "UP_TO_DATE",
129
+ }),
130
+ );
131
+ await waitFor(() =>
132
+ expect(sendInsightsEvent).toHaveBeenCalledWith(
133
+ expect.objectContaining({
134
+ toBundleId: "bundle-id",
135
+ type: "UNCHANGED",
136
+ }),
137
+ ),
138
+ );
139
+ });
140
+
102
141
  it("returns void from init and defers notifyAppReady to the next frame", async () => {
103
142
  vi.useFakeTimers();
104
143
 
@@ -110,7 +149,7 @@ describe("HotUpdater wrap initialization", () => {
110
149
  );
111
150
  vi.stubGlobal("requestAnimationFrame", requestAnimationFrame);
112
151
 
113
- const { client, sendAnalyticsEvent } = createClient();
152
+ const { client, sendInsightsEvent } = createClient();
114
153
  const { init } = await import("./wrap");
115
154
 
116
155
  const result = init({
@@ -123,17 +162,17 @@ describe("HotUpdater wrap initialization", () => {
123
162
 
124
163
  expect(result).toBeUndefined();
125
164
  expect(mocks.readNotifyAppReady).not.toHaveBeenCalled();
126
- expect(sendAnalyticsEvent).not.toHaveBeenCalled();
165
+ expect(sendInsightsEvent).not.toHaveBeenCalled();
127
166
 
128
167
  expect(requestAnimationFrame).toHaveBeenCalled();
129
168
 
130
169
  await vi.runOnlyPendingTimersAsync();
131
170
 
132
171
  expect(mocks.readNotifyAppReady).toHaveBeenCalledWith();
133
- expect(sendAnalyticsEvent).not.toHaveBeenCalled();
172
+ expect(sendInsightsEvent).not.toHaveBeenCalled();
134
173
  });
135
174
 
136
- it("waits for native launch verification before sending analytics", async () => {
175
+ it("waits for native launch verification before sending insights", async () => {
137
176
  vi.useFakeTimers();
138
177
 
139
178
  vi.stubGlobal(
@@ -162,18 +201,18 @@ describe("HotUpdater wrap initialization", () => {
162
201
  ),
163
202
  );
164
203
 
165
- const { client, sendAnalyticsEvent } = createClient();
204
+ const { client, sendInsightsEvent } = createClient();
166
205
  const { init } = await import("./wrap");
167
206
 
168
- init({ analytics: true, client });
207
+ init({ insights: true, client });
169
208
 
170
209
  await vi.runAllTimersAsync();
171
210
 
172
211
  expect(mocks.readNotifyAppReady).toHaveBeenCalledTimes(2);
173
- expect(sendAnalyticsEvent).toHaveBeenCalledTimes(1);
212
+ expect(sendInsightsEvent).toHaveBeenCalledTimes(1);
174
213
  });
175
214
 
176
- it("sends automatic analytics only from init when enabled", async () => {
215
+ it("sends automatic insights only from init when enabled", async () => {
177
216
  vi.useFakeTimers();
178
217
 
179
218
  vi.stubGlobal(
@@ -205,11 +244,11 @@ describe("HotUpdater wrap initialization", () => {
205
244
  username: "alice",
206
245
  });
207
246
 
208
- const { client, sendAnalyticsEvent } = createClient();
247
+ const { client, sendInsightsEvent } = createClient();
209
248
  const { init } = await import("./wrap");
210
249
 
211
250
  init({
212
- analytics: true,
251
+ insights: true,
213
252
  requestHeaders: {
214
253
  Authorization: "Bearer token",
215
254
  },
@@ -219,7 +258,7 @@ describe("HotUpdater wrap initialization", () => {
219
258
 
220
259
  await vi.runOnlyPendingTimersAsync();
221
260
 
222
- expect(sendAnalyticsEvent).toHaveBeenCalledWith({
261
+ expect(sendInsightsEvent).toHaveBeenCalledWith({
223
262
  appVersion: "1.0.0",
224
263
  channel: "production",
225
264
  cohort: "123",
@@ -241,7 +280,7 @@ describe("HotUpdater wrap initialization", () => {
241
280
  });
242
281
  });
243
282
 
244
- it("guards automatic analytics to a single delivery attempt per runtime", async () => {
283
+ it("guards automatic insights to a single delivery attempt per runtime", async () => {
245
284
  vi.useFakeTimers();
246
285
 
247
286
  vi.stubGlobal(
@@ -268,18 +307,18 @@ describe("HotUpdater wrap initialization", () => {
268
307
  ),
269
308
  );
270
309
 
271
- const { client, sendAnalyticsEvent } = createClient();
310
+ const { client, sendInsightsEvent } = createClient();
272
311
  const { init } = await import("./wrap");
273
312
 
274
- init({ analytics: true, client });
275
- init({ analytics: true, client });
313
+ init({ insights: true, client });
314
+ init({ insights: true, client });
276
315
 
277
316
  await vi.runOnlyPendingTimersAsync();
278
317
 
279
- expect(sendAnalyticsEvent).toHaveBeenCalledTimes(1);
318
+ expect(sendInsightsEvent).toHaveBeenCalledTimes(1);
280
319
  });
281
320
 
282
- it("warns without interrupting app readiness when analytics transport fails", async () => {
321
+ it("warns without interrupting app readiness when insights transport fails", async () => {
283
322
  vi.useFakeTimers();
284
323
 
285
324
  const warn = vi.spyOn(console, "warn").mockImplementation(() => {});
@@ -312,7 +351,7 @@ describe("HotUpdater wrap initialization", () => {
312
351
  const { init } = await import("./wrap");
313
352
 
314
353
  init({
315
- analytics: true,
354
+ insights: true,
316
355
  onError,
317
356
  onNotifyAppReady,
318
357
  client,
@@ -322,7 +361,7 @@ describe("HotUpdater wrap initialization", () => {
322
361
 
323
362
  expect(onError).not.toHaveBeenCalled();
324
363
  expect(warn).toHaveBeenCalledWith(
325
- "[HotUpdater] Automatic notifyAppReady analytics failed:",
364
+ "[HotUpdater] Automatic notifyAppReady insights failed:",
326
365
  error,
327
366
  );
328
367
  expect(onNotifyAppReady).toHaveBeenCalledWith({
@@ -344,14 +383,14 @@ describe("HotUpdater wrap initialization", () => {
344
383
 
345
384
  it("preserves wrapped component prop inference", async () => {
346
385
  const { wrap } = await import("./wrap");
347
- const Component: React.ComponentType<{ title: string }> = () => null;
386
+ const Component: ComponentType<{ title: string }> = () => null;
348
387
 
349
388
  const WrappedComponent = wrap({
350
389
  client: createClient().client,
351
390
  updateStrategy: "appVersion",
352
391
  })(Component);
353
392
 
354
- const acceptsTitleProps: React.ComponentType<{ title: string }> =
393
+ const acceptsTitleProps: ComponentType<{ title: string }> =
355
394
  WrappedComponent;
356
395
  expect(acceptsTitleProps).toBe(WrappedComponent);
357
396
  });
package/src/wrap.tsx CHANGED
@@ -2,8 +2,8 @@ import React, { useEffect, useState } from "react";
2
2
 
3
3
  import { checkForUpdate } from "./checkForUpdate";
4
4
  import { useEventCallback } from "./hooks/useEventCallback";
5
- import { getBundleId, reload } from "./native";
6
- import { handleNotifyAppReady } from "./notifyAppReadyAnalytics";
5
+ import { getUpdateId, reload } from "./native";
6
+ import { handleNotifyAppReady } from "./notifyAppReadyInsights";
7
7
  import { useHotUpdaterStore } from "./store";
8
8
  import type {
9
9
  InternalInitOptions,
@@ -46,7 +46,7 @@ export function wrap(
46
46
  setUpdateStatus("CHECK_FOR_UPDATE");
47
47
 
48
48
  const updateInfo = await checkForUpdate({
49
- analytics: restOptions.analytics,
49
+ insights: restOptions.insights,
50
50
  client: restOptions.client,
51
51
  updateStrategy: restOptions.updateStrategy,
52
52
  requestHeaders: restOptions.requestHeaders,
@@ -61,7 +61,7 @@ export function wrap(
61
61
  status: "UP_TO_DATE",
62
62
  shouldForceUpdate: false,
63
63
  message: null,
64
- id: getBundleId(),
64
+ id: getUpdateId(),
65
65
  });
66
66
  setUpdateStatus("UPDATE_PROCESS_COMPLETED");
67
67
  return;