@hot-updater/react-native 1.0.0-rc.0 → 1.0.0-rc.2
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.
- package/android/src/main/java/com/hotupdater/BundleFileStorageService.kt +1 -1
- package/lib/commonjs/checkForUpdate.js +4 -4
- package/lib/commonjs/checkForUpdate.js.map +1 -1
- package/lib/commonjs/checkForUpdate.releaseCatalog.spec.js +10 -10
- package/lib/commonjs/checkForUpdate.releaseCatalog.spec.js.map +1 -1
- package/lib/commonjs/httpClient.js +2 -2
- package/lib/commonjs/httpClient.js.map +1 -1
- package/lib/commonjs/index.js +7 -4
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/index.spec.js +44 -10
- package/lib/commonjs/index.spec.js.map +1 -1
- package/lib/commonjs/native.js +11 -9
- package/lib/commonjs/native.js.map +1 -1
- package/lib/commonjs/native.spec.js +19 -6
- package/lib/commonjs/native.spec.js.map +1 -1
- package/lib/commonjs/{notifyAppReadyAnalytics.boundary.spec.js → notifyAppReadyInsights.boundary.spec.js} +21 -21
- package/lib/commonjs/notifyAppReadyInsights.boundary.spec.js.map +1 -0
- package/lib/commonjs/{notifyAppReadyAnalytics.js → notifyAppReadyInsights.js} +27 -27
- package/lib/commonjs/notifyAppReadyInsights.js.map +1 -0
- package/lib/commonjs/{notifyAppReadyAnalytics.spec.js → notifyAppReadyInsights.spec.js} +29 -29
- package/lib/commonjs/notifyAppReadyInsights.spec.js.map +1 -0
- package/lib/commonjs/{notifyAppReadyAnalytics.test-utils.js → notifyAppReadyInsights.test-utils.js} +3 -3
- package/lib/commonjs/notifyAppReadyInsights.test-utils.js.map +1 -0
- package/lib/commonjs/{notifyAppReadyAnalytics.transport.spec.js → notifyAppReadyInsights.transport.spec.js} +7 -7
- package/lib/commonjs/notifyAppReadyInsights.transport.spec.js.map +1 -0
- package/lib/commonjs/sdkVersion.js +1 -1
- package/lib/commonjs/wrap.js +4 -4
- package/lib/commonjs/wrap.js.map +1 -1
- package/lib/commonjs/wrap.spec.js +24 -24
- package/lib/commonjs/wrap.spec.js.map +1 -1
- package/lib/module/checkForUpdate.js +5 -5
- package/lib/module/checkForUpdate.js.map +1 -1
- package/lib/module/checkForUpdate.releaseCatalog.spec.js +10 -10
- package/lib/module/checkForUpdate.releaseCatalog.spec.js.map +1 -1
- package/lib/module/httpClient.js +2 -2
- package/lib/module/httpClient.js.map +1 -1
- package/lib/module/index.js +8 -5
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.spec.js +44 -10
- package/lib/module/index.spec.js.map +1 -1
- package/lib/module/native.js +9 -7
- package/lib/module/native.js.map +1 -1
- package/lib/module/native.spec.js +19 -6
- package/lib/module/native.spec.js.map +1 -1
- package/lib/module/{notifyAppReadyAnalytics.boundary.spec.js → notifyAppReadyInsights.boundary.spec.js} +16 -16
- package/lib/module/notifyAppReadyInsights.boundary.spec.js.map +1 -0
- package/lib/module/{notifyAppReadyAnalytics.js → notifyAppReadyInsights.js} +27 -27
- package/lib/module/notifyAppReadyInsights.js.map +1 -0
- package/lib/module/{notifyAppReadyAnalytics.spec.js → notifyAppReadyInsights.spec.js} +21 -21
- package/lib/module/notifyAppReadyInsights.spec.js.map +1 -0
- package/lib/module/{notifyAppReadyAnalytics.test-utils.js → notifyAppReadyInsights.test-utils.js} +3 -3
- package/lib/module/notifyAppReadyInsights.test-utils.js.map +1 -0
- package/lib/module/{notifyAppReadyAnalytics.transport.spec.js → notifyAppReadyInsights.transport.spec.js} +4 -4
- package/lib/module/notifyAppReadyInsights.transport.spec.js.map +1 -0
- package/lib/module/sdkVersion.js +1 -1
- package/lib/module/wrap.js +2 -2
- package/lib/module/wrap.js.map +1 -1
- package/lib/module/wrap.spec.js +24 -24
- package/lib/module/wrap.spec.js.map +1 -1
- package/lib/typescript/commonjs/checkForUpdate.d.ts +1 -1
- package/lib/typescript/commonjs/checkForUpdate.d.ts.map +1 -1
- package/lib/typescript/commonjs/httpClient.d.ts +5 -5
- package/lib/typescript/commonjs/httpClient.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +3 -3
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/native.d.ts +7 -5
- package/lib/typescript/commonjs/native.d.ts.map +1 -1
- package/lib/typescript/{module/notifyAppReadyAnalytics.d.ts → commonjs/notifyAppReadyInsights.d.ts} +2 -2
- package/lib/typescript/commonjs/notifyAppReadyInsights.d.ts.map +1 -0
- package/lib/typescript/commonjs/notifyAppReadyInsights.test-utils.d.ts +8 -0
- package/lib/typescript/commonjs/notifyAppReadyInsights.test-utils.d.ts.map +1 -0
- package/lib/typescript/commonjs/sdkVersion.d.ts +1 -1
- package/lib/typescript/commonjs/wrap.types.d.ts +5 -6
- package/lib/typescript/commonjs/wrap.types.d.ts.map +1 -1
- package/lib/typescript/module/checkForUpdate.d.ts +1 -1
- package/lib/typescript/module/checkForUpdate.d.ts.map +1 -1
- package/lib/typescript/module/httpClient.d.ts +5 -5
- package/lib/typescript/module/httpClient.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +3 -3
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/native.d.ts +7 -5
- package/lib/typescript/module/native.d.ts.map +1 -1
- package/lib/typescript/{commonjs/notifyAppReadyAnalytics.d.ts → module/notifyAppReadyInsights.d.ts} +2 -2
- package/lib/typescript/module/notifyAppReadyInsights.d.ts.map +1 -0
- package/lib/typescript/module/notifyAppReadyInsights.test-utils.d.ts +8 -0
- package/lib/typescript/module/notifyAppReadyInsights.test-utils.d.ts.map +1 -0
- package/lib/typescript/module/sdkVersion.d.ts +1 -1
- package/lib/typescript/module/wrap.types.d.ts +5 -6
- package/lib/typescript/module/wrap.types.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/checkForUpdate.releaseCatalog.spec.ts +10 -10
- package/src/checkForUpdate.ts +6 -10
- package/src/httpClient.ts +10 -10
- package/src/index.spec.ts +48 -10
- package/src/index.ts +9 -6
- package/src/native.spec.ts +20 -6
- package/src/native.ts +12 -10
- package/src/{notifyAppReadyAnalytics.boundary.spec.ts → notifyAppReadyInsights.boundary.spec.ts} +17 -17
- package/src/{notifyAppReadyAnalytics.spec.ts → notifyAppReadyInsights.spec.ts} +22 -22
- package/src/{notifyAppReadyAnalytics.test-utils.ts → notifyAppReadyInsights.test-utils.ts} +4 -4
- package/src/{notifyAppReadyAnalytics.transport.spec.ts → notifyAppReadyInsights.transport.spec.ts} +5 -5
- package/src/{notifyAppReadyAnalytics.ts → notifyAppReadyInsights.ts} +33 -33
- package/src/sdkVersion.ts +1 -1
- package/src/wrap.spec.ts +27 -27
- package/src/wrap.tsx +2 -2
- package/src/wrap.types.ts +5 -6
- package/lib/commonjs/notifyAppReadyAnalytics.boundary.spec.js.map +0 -1
- package/lib/commonjs/notifyAppReadyAnalytics.js.map +0 -1
- package/lib/commonjs/notifyAppReadyAnalytics.spec.js.map +0 -1
- package/lib/commonjs/notifyAppReadyAnalytics.test-utils.js.map +0 -1
- package/lib/commonjs/notifyAppReadyAnalytics.transport.spec.js.map +0 -1
- package/lib/module/notifyAppReadyAnalytics.boundary.spec.js.map +0 -1
- package/lib/module/notifyAppReadyAnalytics.js.map +0 -1
- package/lib/module/notifyAppReadyAnalytics.spec.js.map +0 -1
- package/lib/module/notifyAppReadyAnalytics.test-utils.js.map +0 -1
- package/lib/module/notifyAppReadyAnalytics.transport.spec.js.map +0 -1
- package/lib/typescript/commonjs/notifyAppReadyAnalytics.d.ts.map +0 -1
- package/lib/typescript/commonjs/notifyAppReadyAnalytics.test-utils.d.ts +0 -8
- package/lib/typescript/commonjs/notifyAppReadyAnalytics.test-utils.d.ts.map +0 -1
- package/lib/typescript/module/notifyAppReadyAnalytics.d.ts.map +0 -1
- package/lib/typescript/module/notifyAppReadyAnalytics.test-utils.d.ts +0 -8
- package/lib/typescript/module/notifyAppReadyAnalytics.test-utils.d.ts.map +0 -1
package/src/native.ts
CHANGED
|
@@ -215,7 +215,7 @@ const getNativeBundleId = (): string | null => {
|
|
|
215
215
|
};
|
|
216
216
|
|
|
217
217
|
const resolveBundleId = (bundleId: string | null): string => {
|
|
218
|
-
return !bundleId || bundleId === NIL_UUID ?
|
|
218
|
+
return !bundleId || bundleId === NIL_UUID ? getMinBundleId() : bundleId;
|
|
219
219
|
};
|
|
220
220
|
|
|
221
221
|
const getFreshBundleId = (): string => {
|
|
@@ -588,11 +588,13 @@ export function setReloadBehavior(
|
|
|
588
588
|
}
|
|
589
589
|
|
|
590
590
|
/**
|
|
591
|
-
* Fetches the
|
|
591
|
+
* Fetches the minimum bundle id created from the native app build time.
|
|
592
592
|
*
|
|
593
|
-
*
|
|
593
|
+
* Release Catalog selection uses this value as its minimum Release id.
|
|
594
|
+
*
|
|
595
|
+
* @returns {string} The minimum bundle id.
|
|
594
596
|
*/
|
|
595
|
-
export const
|
|
597
|
+
export const getMinBundleId = (): string => {
|
|
596
598
|
const constants = HotUpdaterNative.getConstants();
|
|
597
599
|
return constants.MIN_BUNDLE_ID;
|
|
598
600
|
};
|
|
@@ -685,7 +687,7 @@ export const isChannelSwitched = (): boolean => {
|
|
|
685
687
|
*/
|
|
686
688
|
export const getFingerprintHash = (): string | null => {
|
|
687
689
|
const constants = HotUpdaterNative.getConstants();
|
|
688
|
-
return constants.FINGERPRINT_HASH;
|
|
690
|
+
return constants.FINGERPRINT_HASH ?? null;
|
|
689
691
|
};
|
|
690
692
|
|
|
691
693
|
export const getInstallId = (): string => {
|
|
@@ -781,7 +783,7 @@ export type NotifyAppReadyResult =
|
|
|
781
783
|
toReleaseId?: string;
|
|
782
784
|
};
|
|
783
785
|
|
|
784
|
-
export type
|
|
786
|
+
export type NotifyAppReadyInsightsEvent = {
|
|
785
787
|
type: "UPDATE_APPLIED" | "RECOVERED";
|
|
786
788
|
fromBundleId: string;
|
|
787
789
|
toBundleId: string;
|
|
@@ -889,9 +891,9 @@ const getNotifyAppReadyTransition = (
|
|
|
889
891
|
return null;
|
|
890
892
|
};
|
|
891
893
|
|
|
892
|
-
const
|
|
894
|
+
const getNotifyAppReadyInsightsEvent = (
|
|
893
895
|
result: RawNotifyAppReadyResult,
|
|
894
|
-
):
|
|
896
|
+
): NotifyAppReadyInsightsEvent | null => {
|
|
895
897
|
const transition = getNotifyAppReadyTransition(result);
|
|
896
898
|
|
|
897
899
|
if (!transition || !isPersistedUpdateStrategy(result.updateStrategy)) {
|
|
@@ -936,14 +938,14 @@ const normalizeNotifyAppReadyResult = (
|
|
|
936
938
|
|
|
937
939
|
export const readNotifyAppReady = (): {
|
|
938
940
|
result: NotifyAppReadyResult;
|
|
939
|
-
|
|
941
|
+
insightsEvent: NotifyAppReadyInsightsEvent | null;
|
|
940
942
|
pending: boolean;
|
|
941
943
|
} => {
|
|
942
944
|
const rawResult = readRawNotifyAppReadyResult();
|
|
943
945
|
|
|
944
946
|
return {
|
|
945
947
|
result: normalizeNotifyAppReadyResult(rawResult),
|
|
946
|
-
|
|
948
|
+
insightsEvent: getNotifyAppReadyInsightsEvent(rawResult),
|
|
947
949
|
pending: rawResult.status === "PENDING",
|
|
948
950
|
};
|
|
949
951
|
};
|
package/src/{notifyAppReadyAnalytics.boundary.spec.ts → notifyAppReadyInsights.boundary.spec.ts}
RENAMED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
2
|
|
|
3
3
|
import type {
|
|
4
|
-
|
|
4
|
+
NotifyAppReadyInsightsEvent,
|
|
5
5
|
NotifyAppReadyResult,
|
|
6
6
|
} from "./native";
|
|
7
7
|
import {
|
|
8
8
|
createNotifyReadResult,
|
|
9
9
|
stubNotifyFrame,
|
|
10
|
-
} from "./
|
|
10
|
+
} from "./notifyAppReadyInsights.test-utils";
|
|
11
11
|
|
|
12
12
|
const platformState = vi.hoisted((): { OS: "ios" | "android" } => ({
|
|
13
13
|
OS: "ios",
|
|
@@ -48,7 +48,7 @@ const mocks = vi.hoisted(() => ({
|
|
|
48
48
|
getPersistedUserIdentity: vi.fn(() => ({})),
|
|
49
49
|
readNotifyAppReady: vi.fn<
|
|
50
50
|
() => {
|
|
51
|
-
|
|
51
|
+
insightsEvent: NotifyAppReadyInsightsEvent | null;
|
|
52
52
|
pending: boolean;
|
|
53
53
|
result: NotifyAppReadyResult;
|
|
54
54
|
}
|
|
@@ -78,20 +78,20 @@ vi.mock("./specs/NativeHotUpdater", () => ({
|
|
|
78
78
|
}));
|
|
79
79
|
|
|
80
80
|
const createClient = () => {
|
|
81
|
-
const
|
|
81
|
+
const sendInsightsEvent = vi.fn().mockResolvedValue(undefined);
|
|
82
82
|
return {
|
|
83
83
|
client: {
|
|
84
84
|
createSession: vi.fn(async () => ({
|
|
85
85
|
fetchReleaseCatalog: vi.fn(),
|
|
86
86
|
resolveArtifact: vi.fn(),
|
|
87
|
-
|
|
87
|
+
sendInsightsEvent,
|
|
88
88
|
})),
|
|
89
89
|
},
|
|
90
|
-
|
|
90
|
+
sendInsightsEvent,
|
|
91
91
|
};
|
|
92
92
|
};
|
|
93
93
|
|
|
94
|
-
describe("automatic notifyAppReady
|
|
94
|
+
describe("automatic notifyAppReady insights boundaries", () => {
|
|
95
95
|
beforeEach(() => {
|
|
96
96
|
vi.resetModules();
|
|
97
97
|
vi.unstubAllGlobals();
|
|
@@ -124,7 +124,7 @@ describe("automatic notifyAppReady analytics boundaries", () => {
|
|
|
124
124
|
const { init } = await import("./wrap");
|
|
125
125
|
|
|
126
126
|
init({
|
|
127
|
-
|
|
127
|
+
insights: true,
|
|
128
128
|
client: {
|
|
129
129
|
createSession: vi.fn(async () => {
|
|
130
130
|
throw new Error("baseURL unavailable");
|
|
@@ -138,7 +138,7 @@ describe("automatic notifyAppReady analytics boundaries", () => {
|
|
|
138
138
|
expect(onError).not.toHaveBeenCalled();
|
|
139
139
|
expect(onNotifyAppReady).toHaveBeenCalledWith({ status: "UNCHANGED" });
|
|
140
140
|
expect(warn).toHaveBeenCalledWith(
|
|
141
|
-
"[HotUpdater] Automatic notifyAppReady
|
|
141
|
+
"[HotUpdater] Automatic notifyAppReady insights failed:",
|
|
142
142
|
expect.objectContaining({
|
|
143
143
|
message: "baseURL unavailable",
|
|
144
144
|
}),
|
|
@@ -163,17 +163,17 @@ describe("automatic notifyAppReady analytics boundaries", () => {
|
|
|
163
163
|
} else {
|
|
164
164
|
mocks.getInstallId.mockReturnValue(value);
|
|
165
165
|
}
|
|
166
|
-
const { client,
|
|
166
|
+
const { client, sendInsightsEvent } = createClient();
|
|
167
167
|
const { init } = await import("./wrap");
|
|
168
168
|
|
|
169
|
-
init({
|
|
169
|
+
init({ insights: true, client, onError, onNotifyAppReady });
|
|
170
170
|
await vi.runOnlyPendingTimersAsync();
|
|
171
171
|
|
|
172
|
-
expect(
|
|
172
|
+
expect(sendInsightsEvent).not.toHaveBeenCalled();
|
|
173
173
|
expect(onError).not.toHaveBeenCalled();
|
|
174
174
|
expect(onNotifyAppReady).toHaveBeenCalledWith({ status: "UNCHANGED" });
|
|
175
175
|
expect(warn).toHaveBeenCalledWith(
|
|
176
|
-
"[HotUpdater] Automatic notifyAppReady
|
|
176
|
+
"[HotUpdater] Automatic notifyAppReady insights failed:",
|
|
177
177
|
expect.any(Error),
|
|
178
178
|
);
|
|
179
179
|
warn.mockRestore();
|
|
@@ -197,17 +197,17 @@ describe("automatic notifyAppReady analytics boundaries", () => {
|
|
|
197
197
|
} else {
|
|
198
198
|
mocks.getBundleId.mockReturnValue(value);
|
|
199
199
|
}
|
|
200
|
-
const { client,
|
|
200
|
+
const { client, sendInsightsEvent } = createClient();
|
|
201
201
|
const { init } = await import("./wrap");
|
|
202
202
|
|
|
203
|
-
init({
|
|
203
|
+
init({ insights: true, client, onError, onNotifyAppReady });
|
|
204
204
|
await vi.runOnlyPendingTimersAsync();
|
|
205
205
|
|
|
206
|
-
expect(
|
|
206
|
+
expect(sendInsightsEvent).not.toHaveBeenCalled();
|
|
207
207
|
expect(onError).not.toHaveBeenCalled();
|
|
208
208
|
expect(onNotifyAppReady).toHaveBeenCalledWith({ status: "UNCHANGED" });
|
|
209
209
|
expect(warn).toHaveBeenCalledWith(
|
|
210
|
-
"[HotUpdater] Automatic notifyAppReady
|
|
210
|
+
"[HotUpdater] Automatic notifyAppReady insights failed:",
|
|
211
211
|
expect.any(Error),
|
|
212
212
|
);
|
|
213
213
|
warn.mockRestore();
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
2
|
|
|
3
3
|
import type {
|
|
4
|
-
|
|
4
|
+
NotifyAppReadyInsightsEvent,
|
|
5
5
|
NotifyAppReadyResult,
|
|
6
6
|
} from "./native";
|
|
7
7
|
import {
|
|
8
8
|
createNotifyReadResult,
|
|
9
9
|
stubNotifyFrame,
|
|
10
|
-
} from "./
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
60
|
+
sendInsightsEvent,
|
|
61
61
|
})),
|
|
62
62
|
},
|
|
63
|
-
|
|
63
|
+
sendInsightsEvent,
|
|
64
64
|
};
|
|
65
65
|
};
|
|
66
66
|
|
|
67
|
-
describe("automatic notifyAppReady
|
|
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,
|
|
110
|
+
const { client, sendInsightsEvent } = createClient();
|
|
111
111
|
const onNotifyAppReady = vi.fn();
|
|
112
112
|
const { init } = await import("./wrap");
|
|
113
113
|
|
|
114
114
|
init({
|
|
115
|
-
|
|
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(
|
|
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,
|
|
165
|
+
const { client, sendInsightsEvent } = createClient();
|
|
166
166
|
const onNotifyAppReady = vi.fn();
|
|
167
167
|
const { init } = await import("./wrap");
|
|
168
168
|
|
|
169
|
-
init({
|
|
169
|
+
init({ insights: true, client, onNotifyAppReady });
|
|
170
170
|
await vi.runOnlyPendingTimersAsync();
|
|
171
171
|
|
|
172
|
-
expect(
|
|
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,
|
|
197
|
+
const { client, sendInsightsEvent } = createClient();
|
|
198
198
|
const onNotifyAppReady = vi.fn();
|
|
199
199
|
const { init } = await import("./wrap");
|
|
200
200
|
|
|
201
|
-
init({
|
|
202
|
-
init({
|
|
201
|
+
init({ insights: true, client, onNotifyAppReady });
|
|
202
|
+
init({ insights: true, client, onNotifyAppReady });
|
|
203
203
|
await vi.runOnlyPendingTimersAsync();
|
|
204
204
|
|
|
205
|
-
expect(
|
|
206
|
-
expect(
|
|
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
|
|
231
|
+
it("skips automatic insights when disabled while preserving readiness", async () => {
|
|
232
232
|
stubNotifyFrame();
|
|
233
|
-
const { client,
|
|
233
|
+
const { client, sendInsightsEvent } = createClient();
|
|
234
234
|
const onNotifyAppReady = vi.fn();
|
|
235
235
|
const { init } = await import("./wrap");
|
|
236
236
|
|
|
237
|
-
init({
|
|
237
|
+
init({ insights: false, client, onNotifyAppReady });
|
|
238
238
|
await vi.runOnlyPendingTimersAsync();
|
|
239
239
|
|
|
240
|
-
expect(
|
|
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
|
-
|
|
4
|
+
NotifyAppReadyInsightsEvent,
|
|
5
5
|
NotifyAppReadyResult,
|
|
6
6
|
} from "./native";
|
|
7
7
|
|
|
8
8
|
export const createNotifyReadResult = (
|
|
9
9
|
result: NotifyAppReadyResult = { status: "UNCHANGED" },
|
|
10
|
-
|
|
10
|
+
insightsEvent: NotifyAppReadyInsightsEvent | null = null,
|
|
11
11
|
pending = false,
|
|
12
12
|
): {
|
|
13
|
-
|
|
13
|
+
insightsEvent: NotifyAppReadyInsightsEvent | null;
|
|
14
14
|
pending: boolean;
|
|
15
15
|
result: NotifyAppReadyResult;
|
|
16
16
|
} => ({
|
|
17
|
-
|
|
17
|
+
insightsEvent,
|
|
18
18
|
pending,
|
|
19
19
|
result,
|
|
20
20
|
});
|
package/src/{notifyAppReadyAnalytics.transport.spec.ts → notifyAppReadyInsights.transport.spec.ts}
RENAMED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
2
|
|
|
3
3
|
import type {
|
|
4
|
-
|
|
4
|
+
NotifyAppReadyInsightsEvent,
|
|
5
5
|
NotifyAppReadyResult,
|
|
6
6
|
} from "./native";
|
|
7
7
|
import {
|
|
8
8
|
createNotifyReadResult,
|
|
9
9
|
stubNotifyFrame,
|
|
10
|
-
} from "./
|
|
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
|
-
|
|
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({
|
|
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
|
|
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 {
|
|
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
|
|
13
|
+
type NotifyAppReadyInsightsEvent,
|
|
14
14
|
type NotifyAppReadyResult,
|
|
15
15
|
readNotifyAppReady,
|
|
16
16
|
} from "./native";
|
|
17
17
|
|
|
18
18
|
export type NotifyAppReadyOptions = {
|
|
19
|
-
|
|
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
|
|
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
|
|
51
|
+
const buildNotifyAppReadyInsightsParams = (
|
|
52
52
|
nativeResult: NotifyAppReadyResult,
|
|
53
|
-
|
|
53
|
+
insightsEvent: NotifyAppReadyInsightsEvent | null,
|
|
54
54
|
options: Pick<NotifyAppReadyOptions, "requestHeaders" | "requestTimeout">,
|
|
55
|
-
):
|
|
55
|
+
): InsightsEventParams => {
|
|
56
56
|
const appVersion = getAppVersion();
|
|
57
57
|
|
|
58
58
|
if (!appVersion) {
|
|
59
59
|
throw new Error(
|
|
60
|
-
"[HotUpdater] Automatic
|
|
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
|
|
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:
|
|
81
|
+
fromReleaseId: insightsEvent?.fromReleaseId ?? null,
|
|
82
82
|
installId,
|
|
83
83
|
platform,
|
|
84
84
|
requestHeaders: options.requestHeaders,
|
|
85
85
|
requestTimeout: options.requestTimeout,
|
|
86
|
-
toReleaseId:
|
|
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
|
|
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 (!
|
|
111
|
+
if (!insightsEvent) {
|
|
112
112
|
throw new Error(
|
|
113
|
-
"[HotUpdater] Native launch report is missing persisted metadata required for automatic
|
|
113
|
+
"[HotUpdater] Native launch report is missing persisted metadata required for automatic insights.",
|
|
114
114
|
);
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
-
switch (
|
|
117
|
+
switch (insightsEvent.type) {
|
|
118
118
|
case "UPDATE_APPLIED":
|
|
119
119
|
return {
|
|
120
120
|
...commonParams,
|
|
121
|
-
fromBundleId:
|
|
122
|
-
toBundleId:
|
|
121
|
+
fromBundleId: insightsEvent.fromBundleId,
|
|
122
|
+
toBundleId: insightsEvent.toBundleId,
|
|
123
123
|
type: "UPDATE_APPLIED",
|
|
124
|
-
updateStrategy:
|
|
124
|
+
updateStrategy: insightsEvent.updateStrategy,
|
|
125
125
|
};
|
|
126
126
|
case "RECOVERED":
|
|
127
127
|
return {
|
|
128
128
|
...commonParams,
|
|
129
|
-
fromBundleId:
|
|
130
|
-
toBundleId:
|
|
129
|
+
fromBundleId: insightsEvent.fromBundleId,
|
|
130
|
+
toBundleId: insightsEvent.toBundleId,
|
|
131
131
|
type: "RECOVERED",
|
|
132
|
-
updateStrategy:
|
|
132
|
+
updateStrategy: insightsEvent.updateStrategy,
|
|
133
133
|
};
|
|
134
134
|
default:
|
|
135
|
-
return assertNever(
|
|
135
|
+
return assertNever(insightsEvent.type);
|
|
136
136
|
}
|
|
137
137
|
default:
|
|
138
138
|
return assertNever(nativeResult);
|
|
139
139
|
}
|
|
140
140
|
};
|
|
141
141
|
|
|
142
|
-
const
|
|
142
|
+
const maybeSendAutomaticInsights = async (
|
|
143
143
|
options: NotifyAppReadyOptions,
|
|
144
144
|
nativeResult: NotifyAppReadyResult,
|
|
145
|
-
|
|
145
|
+
insightsEvent: NotifyAppReadyInsightsEvent | null,
|
|
146
146
|
): Promise<void> => {
|
|
147
|
-
if (!options.
|
|
147
|
+
if (!options.insights || didAttemptAutomaticInsights) {
|
|
148
148
|
return;
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
-
|
|
151
|
+
didAttemptAutomaticInsights = true;
|
|
152
152
|
|
|
153
|
-
if (nativeResult.status !== "UNCHANGED" && !
|
|
153
|
+
if (nativeResult.status !== "UNCHANGED" && !insightsEvent) {
|
|
154
154
|
throw new Error(
|
|
155
|
-
"[HotUpdater] Native launch report is missing persisted metadata required for automatic
|
|
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.
|
|
161
|
-
|
|
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 {
|
|
175
|
+
const { insightsEvent, result: nativeResult } = nativeReadResult;
|
|
176
176
|
|
|
177
177
|
try {
|
|
178
|
-
await
|
|
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
|
|
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
|
+
export const HOT_UPDATER_SDK_VERSION = "1.0.0-rc.2";
|