@hot-updater/react-native 1.0.0-rc.1 → 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 +3 -3
- package/lib/commonjs/checkForUpdate.js.map +1 -1
- package/lib/commonjs/checkForUpdate.releaseCatalog.spec.js +9 -9
- 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 +5 -2
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/index.spec.js +41 -7
- package/lib/commonjs/index.spec.js.map +1 -1
- package/lib/commonjs/native.js +3 -3
- 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 +3 -3
- package/lib/module/checkForUpdate.js.map +1 -1
- package/lib/module/checkForUpdate.releaseCatalog.spec.js +9 -9
- 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 +5 -2
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.spec.js +41 -7
- package/lib/module/index.spec.js.map +1 -1
- package/lib/module/native.js +3 -3
- 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.map +1 -1
- package/lib/typescript/commonjs/native.d.ts +2 -2
- 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.map +1 -1
- package/lib/typescript/module/native.d.ts +2 -2
- 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 +9 -9
- package/src/checkForUpdate.ts +4 -8
- package/src/httpClient.ts +10 -10
- package/src/index.spec.ts +45 -7
- package/src/index.ts +6 -3
- package/src/native.spec.ts +20 -6
- package/src/native.ts +6 -6
- 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/httpClient.ts
CHANGED
|
@@ -27,7 +27,7 @@ export interface ArtifactRequest {
|
|
|
27
27
|
readonly requestTimeout?: number;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
interface
|
|
30
|
+
interface InsightsEventCommonParams {
|
|
31
31
|
readonly installId: string;
|
|
32
32
|
readonly userId?: string;
|
|
33
33
|
readonly username?: string;
|
|
@@ -42,30 +42,30 @@ interface AnalyticsEventCommonParams {
|
|
|
42
42
|
readonly requestTimeout?: number;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
type
|
|
45
|
+
type InsightsTransitionEventParams = InsightsEventCommonParams & {
|
|
46
46
|
readonly type: "UPDATE_APPLIED" | "RECOVERED" | "RELEASE_ADOPTED";
|
|
47
47
|
readonly fromBundleId: string;
|
|
48
48
|
readonly toBundleId: string;
|
|
49
49
|
readonly updateStrategy: "fingerprint" | "appVersion";
|
|
50
50
|
};
|
|
51
51
|
|
|
52
|
-
type
|
|
52
|
+
type InsightsUnchangedEventParams = InsightsEventCommonParams & {
|
|
53
53
|
readonly type: "UNCHANGED";
|
|
54
54
|
readonly fromBundleId: null;
|
|
55
55
|
readonly toBundleId: string;
|
|
56
56
|
readonly updateStrategy: null;
|
|
57
57
|
};
|
|
58
58
|
|
|
59
|
-
export type
|
|
60
|
-
|
|
|
61
|
-
|
|
|
59
|
+
export type InsightsEventParams =
|
|
60
|
+
| InsightsTransitionEventParams
|
|
61
|
+
| InsightsUnchangedEventParams;
|
|
62
62
|
|
|
63
63
|
export interface HotUpdaterHttpSession {
|
|
64
64
|
fetchReleaseCatalog: (
|
|
65
65
|
params: ReleaseCatalogRequest,
|
|
66
66
|
) => Promise<ReleaseCatalog>;
|
|
67
67
|
resolveArtifact: (params: ArtifactRequest) => Promise<ArtifactInfo>;
|
|
68
|
-
|
|
68
|
+
sendInsightsEvent: (params: InsightsEventParams) => Promise<void>;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
export interface HotUpdaterHttpClient {
|
|
@@ -147,9 +147,9 @@ const resolveArtifactUrls = (
|
|
|
147
147
|
}),
|
|
148
148
|
});
|
|
149
149
|
|
|
150
|
-
const
|
|
150
|
+
const sendInsightsEvent = async (
|
|
151
151
|
baseURL: string,
|
|
152
|
-
params:
|
|
152
|
+
params: InsightsEventParams,
|
|
153
153
|
): Promise<void> => {
|
|
154
154
|
const controller = new AbortController();
|
|
155
155
|
const timeoutId = setTimeout(() => {
|
|
@@ -250,7 +250,7 @@ const createSession = (baseURL: string): HotUpdaterHttpSession => ({
|
|
|
250
250
|
});
|
|
251
251
|
return resolveArtifactUrls(baseURL, info);
|
|
252
252
|
},
|
|
253
|
-
|
|
253
|
+
sendInsightsEvent: (params) => sendInsightsEvent(baseURL, params),
|
|
254
254
|
});
|
|
255
255
|
|
|
256
256
|
/** Creates the private HTTP client used by HotUpdater.init and HotUpdater.wrap. */
|
package/src/index.spec.ts
CHANGED
|
@@ -103,7 +103,7 @@ describe("HotUpdater client initialization", () => {
|
|
|
103
103
|
const HotUpdater = await importHotUpdater();
|
|
104
104
|
|
|
105
105
|
HotUpdater.init({
|
|
106
|
-
|
|
106
|
+
insights: true,
|
|
107
107
|
baseURL: "https://updates.example.com",
|
|
108
108
|
requestHeaders: { Authorization: "Bearer token" },
|
|
109
109
|
requestTimeout: 1000,
|
|
@@ -113,7 +113,7 @@ describe("HotUpdater client initialization", () => {
|
|
|
113
113
|
"https://updates.example.com",
|
|
114
114
|
);
|
|
115
115
|
expect(mocks.init).toHaveBeenCalledWith({
|
|
116
|
-
|
|
116
|
+
insights: true,
|
|
117
117
|
client,
|
|
118
118
|
requestHeaders: { Authorization: "Bearer token" },
|
|
119
119
|
requestTimeout: 1000,
|
|
@@ -130,6 +130,44 @@ describe("HotUpdater client initialization", () => {
|
|
|
130
130
|
expect(resolveBaseURL).not.toHaveBeenCalled();
|
|
131
131
|
});
|
|
132
132
|
|
|
133
|
+
it("enables insights by default for init and wrap", async () => {
|
|
134
|
+
const HotUpdater = await importHotUpdater();
|
|
135
|
+
|
|
136
|
+
HotUpdater.init({ baseURL: "https://updates.example.com" });
|
|
137
|
+
HotUpdater.wrap({
|
|
138
|
+
baseURL: "https://updates.example.com",
|
|
139
|
+
updateStrategy: "appVersion",
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
expect(mocks.init).toHaveBeenCalledWith(
|
|
143
|
+
expect.objectContaining({ insights: true }),
|
|
144
|
+
);
|
|
145
|
+
expect(mocks.wrap).toHaveBeenCalledWith(
|
|
146
|
+
expect.objectContaining({ insights: true }),
|
|
147
|
+
);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it("preserves an explicit insights opt-out", async () => {
|
|
151
|
+
const HotUpdater = await importHotUpdater();
|
|
152
|
+
|
|
153
|
+
HotUpdater.init({
|
|
154
|
+
baseURL: "https://updates.example.com",
|
|
155
|
+
insights: false,
|
|
156
|
+
});
|
|
157
|
+
HotUpdater.wrap({
|
|
158
|
+
baseURL: "https://updates.example.com",
|
|
159
|
+
insights: false,
|
|
160
|
+
updateStrategy: "appVersion",
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
expect(mocks.init).toHaveBeenCalledWith(
|
|
164
|
+
expect.objectContaining({ insights: false }),
|
|
165
|
+
);
|
|
166
|
+
expect(mocks.wrap).toHaveBeenCalledWith(
|
|
167
|
+
expect.objectContaining({ insights: false }),
|
|
168
|
+
);
|
|
169
|
+
});
|
|
170
|
+
|
|
133
171
|
it("requires baseURL and rejects the removed resolver shape", async () => {
|
|
134
172
|
const HotUpdater = await importHotUpdater();
|
|
135
173
|
|
|
@@ -171,13 +209,13 @@ describe("HotUpdater client initialization", () => {
|
|
|
171
209
|
expect(wrapOptions.updateStrategy).toBe("appVersion");
|
|
172
210
|
});
|
|
173
211
|
|
|
174
|
-
it("merges settings and carries the
|
|
212
|
+
it("merges settings and carries the insights gate to checks", async () => {
|
|
175
213
|
const client = { createSession: vi.fn() };
|
|
176
214
|
mocks.createHttpClient.mockReturnValue(client as never);
|
|
177
215
|
const checkOnError = vi.fn();
|
|
178
216
|
const HotUpdater = await importHotUpdater();
|
|
179
217
|
HotUpdater.init({
|
|
180
|
-
|
|
218
|
+
insights: true,
|
|
181
219
|
baseURL: "https://updates.example.com",
|
|
182
220
|
requestHeaders: { Authorization: "Bearer token" },
|
|
183
221
|
requestTimeout: 1000,
|
|
@@ -190,7 +228,7 @@ describe("HotUpdater client initialization", () => {
|
|
|
190
228
|
});
|
|
191
229
|
|
|
192
230
|
expect(mocks.checkForUpdate).toHaveBeenCalledWith({
|
|
193
|
-
|
|
231
|
+
insights: true,
|
|
194
232
|
client,
|
|
195
233
|
onError: checkOnError,
|
|
196
234
|
requestHeaders: {
|
|
@@ -208,13 +246,13 @@ describe("HotUpdater client initialization", () => {
|
|
|
208
246
|
const HotUpdater = await importHotUpdater();
|
|
209
247
|
|
|
210
248
|
HotUpdater.wrap({
|
|
211
|
-
|
|
249
|
+
insights: true,
|
|
212
250
|
baseURL: "https://updates.example.com",
|
|
213
251
|
updateStrategy: "appVersion",
|
|
214
252
|
});
|
|
215
253
|
|
|
216
254
|
expect(mocks.wrap).toHaveBeenCalledWith({
|
|
217
|
-
|
|
255
|
+
insights: true,
|
|
218
256
|
client,
|
|
219
257
|
updateStrategy: "appVersion",
|
|
220
258
|
});
|
package/src/index.ts
CHANGED
|
@@ -101,12 +101,13 @@ function createHotUpdaterClient() {
|
|
|
101
101
|
|
|
102
102
|
// Global configuration stored from wrap
|
|
103
103
|
const globalConfig: {
|
|
104
|
-
|
|
104
|
+
insights: boolean;
|
|
105
105
|
client: HotUpdaterHttpClient | null;
|
|
106
106
|
requestHeaders?: Record<string, string>;
|
|
107
107
|
requestTimeout?: number;
|
|
108
108
|
onError?: (error: unknown) => void;
|
|
109
109
|
} = {
|
|
110
|
+
insights: true,
|
|
110
111
|
client: null,
|
|
111
112
|
};
|
|
112
113
|
|
|
@@ -158,6 +159,7 @@ function createHotUpdaterClient() {
|
|
|
158
159
|
const { baseURL, ...rest } = autoOptions;
|
|
159
160
|
return {
|
|
160
161
|
...rest,
|
|
162
|
+
insights: rest.insights ?? true,
|
|
161
163
|
client: createHttpClient(baseURL),
|
|
162
164
|
};
|
|
163
165
|
}
|
|
@@ -177,6 +179,7 @@ function createHotUpdaterClient() {
|
|
|
177
179
|
const { baseURL, ...baseURLRest } = rest;
|
|
178
180
|
return {
|
|
179
181
|
...baseURLRest,
|
|
182
|
+
insights: baseURLRest.insights ?? true,
|
|
180
183
|
client: createHttpClient(baseURL),
|
|
181
184
|
};
|
|
182
185
|
}
|
|
@@ -188,7 +191,7 @@ function createHotUpdaterClient() {
|
|
|
188
191
|
normalizedOptions: InternalInitOptions | InternalWrapOptions,
|
|
189
192
|
options: HotUpdaterOptions | HotUpdaterInitOptions,
|
|
190
193
|
) => {
|
|
191
|
-
globalConfig.
|
|
194
|
+
globalConfig.insights = normalizedOptions.insights ?? true;
|
|
192
195
|
globalConfig.client = normalizedOptions.client;
|
|
193
196
|
globalConfig.requestHeaders = options.requestHeaders;
|
|
194
197
|
globalConfig.requestTimeout = options.requestTimeout;
|
|
@@ -448,7 +451,7 @@ function createHotUpdaterClient() {
|
|
|
448
451
|
|
|
449
452
|
const mergedConfig: InternalCheckForUpdateOptions = {
|
|
450
453
|
...config,
|
|
451
|
-
|
|
454
|
+
insights: globalConfig.insights,
|
|
452
455
|
client,
|
|
453
456
|
requestHeaders: {
|
|
454
457
|
...globalConfig.requestHeaders,
|
package/src/native.spec.ts
CHANGED
|
@@ -157,7 +157,7 @@ describe("notifyAppReady", () => {
|
|
|
157
157
|
toBundleId: "bundle-122",
|
|
158
158
|
});
|
|
159
159
|
expect(readNotifyAppReady()).toEqual({
|
|
160
|
-
|
|
160
|
+
insightsEvent: {
|
|
161
161
|
fromBundleId: "bundle-123",
|
|
162
162
|
toBundleId: "bundle-122",
|
|
163
163
|
type: "RECOVERED",
|
|
@@ -184,13 +184,13 @@ describe("notifyAppReady", () => {
|
|
|
184
184
|
|
|
185
185
|
expect(notifyAppReady()).toEqual({ status: "UNCHANGED" });
|
|
186
186
|
expect(readNotifyAppReady()).toEqual({
|
|
187
|
-
|
|
187
|
+
insightsEvent: null,
|
|
188
188
|
pending: false,
|
|
189
189
|
result: { status: "UNCHANGED" },
|
|
190
190
|
});
|
|
191
191
|
});
|
|
192
192
|
|
|
193
|
-
it("returns UNCHANGED when automatic
|
|
193
|
+
it("returns UNCHANGED when automatic insights metadata is incomplete", async () => {
|
|
194
194
|
nativeModuleMock.notifyAppReady.mockReturnValue({
|
|
195
195
|
status: "UPDATE_APPLIED",
|
|
196
196
|
});
|
|
@@ -199,7 +199,7 @@ describe("notifyAppReady", () => {
|
|
|
199
199
|
|
|
200
200
|
expect(notifyAppReady()).toEqual({ status: "UNCHANGED" });
|
|
201
201
|
expect(readNotifyAppReady()).toEqual({
|
|
202
|
-
|
|
202
|
+
insightsEvent: null,
|
|
203
203
|
pending: false,
|
|
204
204
|
result: { status: "UNCHANGED" },
|
|
205
205
|
});
|
|
@@ -212,7 +212,7 @@ describe("notifyAppReady", () => {
|
|
|
212
212
|
|
|
213
213
|
expect(notifyAppReady()).toEqual({ status: "UNCHANGED" });
|
|
214
214
|
expect(readNotifyAppReady()).toEqual({
|
|
215
|
-
|
|
215
|
+
insightsEvent: null,
|
|
216
216
|
pending: false,
|
|
217
217
|
result: { status: "UNCHANGED" },
|
|
218
218
|
});
|
|
@@ -225,7 +225,7 @@ describe("notifyAppReady", () => {
|
|
|
225
225
|
|
|
226
226
|
expect(notifyAppReady()).toEqual({ status: "UNCHANGED" });
|
|
227
227
|
expect(readNotifyAppReady()).toEqual({
|
|
228
|
-
|
|
228
|
+
insightsEvent: null,
|
|
229
229
|
pending: true,
|
|
230
230
|
result: { status: "UNCHANGED" },
|
|
231
231
|
});
|
|
@@ -728,6 +728,20 @@ describe("notifyAppReady", () => {
|
|
|
728
728
|
expect(getInstallId()).toBe("install-123");
|
|
729
729
|
});
|
|
730
730
|
|
|
731
|
+
it("normalizes an omitted native fingerprint constant to null", async () => {
|
|
732
|
+
nativeModuleMock.getConstants.mockReturnValue({
|
|
733
|
+
APP_VERSION: null,
|
|
734
|
+
CHANNEL: "production",
|
|
735
|
+
DEFAULT_CHANNEL: "production",
|
|
736
|
+
FINGERPRINT_HASH: undefined as unknown as null,
|
|
737
|
+
MIN_BUNDLE_ID: "min-bundle-id",
|
|
738
|
+
});
|
|
739
|
+
|
|
740
|
+
const { getFingerprintHash } = await import("./native");
|
|
741
|
+
|
|
742
|
+
expect(getFingerprintHash()).toBeNull();
|
|
743
|
+
});
|
|
744
|
+
|
|
731
745
|
it("throws when native SDK does not expose getInstallId", async () => {
|
|
732
746
|
const nativeModule = nativeModuleMock as typeof nativeModuleMock & {
|
|
733
747
|
getInstallId?: typeof nativeModuleMock.getInstallId;
|
package/src/native.ts
CHANGED
|
@@ -687,7 +687,7 @@ export const isChannelSwitched = (): boolean => {
|
|
|
687
687
|
*/
|
|
688
688
|
export const getFingerprintHash = (): string | null => {
|
|
689
689
|
const constants = HotUpdaterNative.getConstants();
|
|
690
|
-
return constants.FINGERPRINT_HASH;
|
|
690
|
+
return constants.FINGERPRINT_HASH ?? null;
|
|
691
691
|
};
|
|
692
692
|
|
|
693
693
|
export const getInstallId = (): string => {
|
|
@@ -783,7 +783,7 @@ export type NotifyAppReadyResult =
|
|
|
783
783
|
toReleaseId?: string;
|
|
784
784
|
};
|
|
785
785
|
|
|
786
|
-
export type
|
|
786
|
+
export type NotifyAppReadyInsightsEvent = {
|
|
787
787
|
type: "UPDATE_APPLIED" | "RECOVERED";
|
|
788
788
|
fromBundleId: string;
|
|
789
789
|
toBundleId: string;
|
|
@@ -891,9 +891,9 @@ const getNotifyAppReadyTransition = (
|
|
|
891
891
|
return null;
|
|
892
892
|
};
|
|
893
893
|
|
|
894
|
-
const
|
|
894
|
+
const getNotifyAppReadyInsightsEvent = (
|
|
895
895
|
result: RawNotifyAppReadyResult,
|
|
896
|
-
):
|
|
896
|
+
): NotifyAppReadyInsightsEvent | null => {
|
|
897
897
|
const transition = getNotifyAppReadyTransition(result);
|
|
898
898
|
|
|
899
899
|
if (!transition || !isPersistedUpdateStrategy(result.updateStrategy)) {
|
|
@@ -938,14 +938,14 @@ const normalizeNotifyAppReadyResult = (
|
|
|
938
938
|
|
|
939
939
|
export const readNotifyAppReady = (): {
|
|
940
940
|
result: NotifyAppReadyResult;
|
|
941
|
-
|
|
941
|
+
insightsEvent: NotifyAppReadyInsightsEvent | null;
|
|
942
942
|
pending: boolean;
|
|
943
943
|
} => {
|
|
944
944
|
const rawResult = readRawNotifyAppReadyResult();
|
|
945
945
|
|
|
946
946
|
return {
|
|
947
947
|
result: normalizeNotifyAppReadyResult(rawResult),
|
|
948
|
-
|
|
948
|
+
insightsEvent: getNotifyAppReadyInsightsEvent(rawResult),
|
|
949
949
|
pending: rawResult.status === "PENDING",
|
|
950
950
|
};
|
|
951
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 {
|