@hot-updater/react-native 1.1.0 → 1.1.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/ActivityStartGate.kt +1 -1
- package/android/src/main/java/com/hotupdater/HotUpdaterImpl.kt +91 -4
- package/android/src/main/java/com/hotupdater/HotUpdaterRecoveryAttribution.kt +2 -1
- package/android/src/main/java/com/hotupdater/HotUpdaterRecoveryManager.kt +27 -5
- package/android/src/main/java/com/hotupdater/HotUpdaterRestartActivity.kt +39 -0
- package/android/src/main/java/com/hotupdater/NativeUpdateCheck.kt +2 -0
- package/android/src/main/java/com/hotupdater/NativeUpdateChecker.kt +9 -4
- package/android/src/main/java/com/hotupdater/PostCrashUpdateCheck.kt +195 -0
- package/ios/HotUpdater/Internal/HotUpdaterImpl.swift +125 -3
- package/ios/HotUpdater/Internal/HotUpdaterLaunchRecovery.swift +90 -10
- package/ios/HotUpdater/Internal/HotUpdaterNativeUpdates.swift +2 -0
- package/ios/HotUpdater/Internal/NativeUpdateCheck.swift +15 -4
- package/ios/HotUpdater/Internal/PostCrashUpdateCheck.swift +248 -0
- package/ios/HotUpdater/Package.swift +1 -0
- package/lib/commonjs/checkForUpdate.js +10 -1
- package/lib/commonjs/checkForUpdate.js.map +1 -1
- package/lib/commonjs/httpClient.js +1 -0
- package/lib/commonjs/httpClient.js.map +1 -1
- package/lib/commonjs/recoveryCheckConfig.js +58 -0
- package/lib/commonjs/recoveryCheckConfig.js.map +1 -0
- package/lib/commonjs/sdkVersion.js +1 -1
- package/lib/module/checkForUpdate.js +10 -1
- package/lib/module/checkForUpdate.js.map +1 -1
- package/lib/module/httpClient.js +1 -0
- package/lib/module/httpClient.js.map +1 -1
- package/lib/module/recoveryCheckConfig.js +54 -0
- package/lib/module/recoveryCheckConfig.js.map +1 -0
- package/lib/module/sdkVersion.js +1 -1
- package/lib/typescript/commonjs/checkForUpdate.d.ts.map +1 -1
- package/lib/typescript/commonjs/httpClient.d.ts +2 -0
- package/lib/typescript/commonjs/httpClient.d.ts.map +1 -1
- package/lib/typescript/commonjs/recoveryCheckConfig.d.ts +28 -0
- package/lib/typescript/commonjs/recoveryCheckConfig.d.ts.map +1 -0
- package/lib/typescript/commonjs/sdkVersion.d.ts +1 -1
- package/lib/typescript/module/checkForUpdate.d.ts.map +1 -1
- package/lib/typescript/module/httpClient.d.ts +2 -0
- package/lib/typescript/module/httpClient.d.ts.map +1 -1
- package/lib/typescript/module/recoveryCheckConfig.d.ts +28 -0
- package/lib/typescript/module/recoveryCheckConfig.d.ts.map +1 -0
- package/lib/typescript/module/sdkVersion.d.ts +1 -1
- package/package.json +4 -4
- package/src/checkForUpdate.ts +10 -1
- package/src/httpClient.ts +3 -0
- package/src/recoveryCheckConfig.ts +68 -0
- package/src/sdkVersion.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hot-updater/react-native",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"description": "React Native OTA solution for self-hosted",
|
|
5
5
|
"source": "./src/index.ts",
|
|
6
6
|
"main": "./lib/commonjs/index.js",
|
|
@@ -124,9 +124,9 @@
|
|
|
124
124
|
},
|
|
125
125
|
"dependencies": {
|
|
126
126
|
"use-sync-external-store": "1.5.0",
|
|
127
|
-
"@hot-updater/protocol": "1.1.
|
|
128
|
-
"@hot-updater/plugin-
|
|
129
|
-
"@hot-updater/plugin-
|
|
127
|
+
"@hot-updater/protocol": "1.1.2",
|
|
128
|
+
"@hot-updater/plugin-remote-config": "1.1.2",
|
|
129
|
+
"@hot-updater/plugin-insights": "1.1.2"
|
|
130
130
|
},
|
|
131
131
|
"scripts": {
|
|
132
132
|
"build": "node ./scripts/sync-sdk-version.mjs run -- bob build",
|
package/src/checkForUpdate.ts
CHANGED
|
@@ -37,6 +37,7 @@ import {
|
|
|
37
37
|
stageBundle,
|
|
38
38
|
supportsArtifactFiles,
|
|
39
39
|
} from "./native";
|
|
40
|
+
import { saveRecoveryCheckConfig } from "./recoveryCheckConfig";
|
|
40
41
|
import { hotUpdaterStore } from "./store";
|
|
41
42
|
import { classifyUpdateError, InvalidUpdateResponseError } from "./updateError";
|
|
42
43
|
|
|
@@ -214,9 +215,17 @@ async function checkForReleaseCatalogUpdate(input: {
|
|
|
214
215
|
requestTimeout: options.requestTimeout,
|
|
215
216
|
updateStrategy: options.updateStrategy,
|
|
216
217
|
});
|
|
218
|
+
if (catalog !== null) validateCatalog(catalog, expectedScope);
|
|
219
|
+
// The server answered with a valid catalog, or with none yet: only such a
|
|
220
|
+
// request replaces the saved one, so one that fails keeps the last.
|
|
221
|
+
saveRecoveryCheckConfig({
|
|
222
|
+
baseURL: session.baseURL,
|
|
223
|
+
requestHeaders: options.requestHeaders,
|
|
224
|
+
requestTimeout: options.requestTimeout,
|
|
225
|
+
updateStrategy: options.updateStrategy,
|
|
226
|
+
});
|
|
217
227
|
// The server says this scope has no catalog yet: no update, not a failure.
|
|
218
228
|
if (catalog === null) return null;
|
|
219
|
-
validateCatalog(catalog, expectedScope);
|
|
220
229
|
const catalogId = catalog.catalogId;
|
|
221
230
|
const scopeKey = catalog.scopeKey;
|
|
222
231
|
|
package/src/httpClient.ts
CHANGED
|
@@ -59,6 +59,8 @@ export type ResolvedArtifact =
|
|
|
59
59
|
};
|
|
60
60
|
|
|
61
61
|
export interface HotUpdaterHttpSession {
|
|
62
|
+
/** The server this session requests, with a baseURL function resolved. */
|
|
63
|
+
readonly baseURL: string;
|
|
62
64
|
/** Resolves to null when the server says the scope has no catalog, so no update. */
|
|
63
65
|
fetchReleaseCatalog: (
|
|
64
66
|
params: ReleaseCatalogRequest,
|
|
@@ -143,6 +145,7 @@ const createSession = (
|
|
|
143
145
|
baseURL: string,
|
|
144
146
|
onResponse?: (response: UpdateHttpResponse) => void,
|
|
145
147
|
): HotUpdaterHttpSession => ({
|
|
148
|
+
baseURL,
|
|
146
149
|
fetchReleaseCatalog: async (params): Promise<ReleaseCatalog | null> => {
|
|
147
150
|
const channelKey = encodeChannelKey(params.channel);
|
|
148
151
|
let strategyValue: string;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { CheckForUpdateOptions } from "./checkForUpdate";
|
|
2
|
+
import { DEFAULT_REQUEST_TIMEOUT_MS } from "./fetchUpdateResponse";
|
|
3
|
+
import { setStorageItem } from "./native";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The native key-value entry native reads after a crash: once a launch of the
|
|
7
|
+
* app ends in a crash that doesn't roll back, the next launch checks for an
|
|
8
|
+
* update natively, without the app's JavaScript, whose own update flow may be
|
|
9
|
+
* what crashes. Native knows no server of its own, so the app's update checks
|
|
10
|
+
* leave it here. A device that never checked, such as one whose user hasn't
|
|
11
|
+
* accepted the privacy terms yet, has none, so native sends no request.
|
|
12
|
+
*/
|
|
13
|
+
export const RECOVERY_CHECK_CONFIG_KEY = "hot-updater/recovery-check-config";
|
|
14
|
+
|
|
15
|
+
/** What native reads; native rejects any other `version`. */
|
|
16
|
+
interface RecoveryCheckConfig {
|
|
17
|
+
readonly version: 1;
|
|
18
|
+
readonly baseURL: string;
|
|
19
|
+
readonly requestHeaders: Record<string, string>;
|
|
20
|
+
readonly requestTimeoutMs: number;
|
|
21
|
+
readonly updateStrategy: CheckForUpdateOptions["updateStrategy"];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const write = (config: RecoveryCheckConfig) => {
|
|
25
|
+
// An update check never fails because native couldn't keep this.
|
|
26
|
+
try {
|
|
27
|
+
setStorageItem(RECOVERY_CHECK_CONFIG_KEY, JSON.stringify(config));
|
|
28
|
+
} catch (error) {
|
|
29
|
+
console.warn(
|
|
30
|
+
"[HotUpdater] Failed to save the recovery check config",
|
|
31
|
+
error,
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* The headers as the request sent them: `Headers` lowercases names and
|
|
38
|
+
* joins two spellings of one name, as the catalog request did, so native
|
|
39
|
+
* repeats the same values instead of picking one of the spellings.
|
|
40
|
+
*/
|
|
41
|
+
const sentHeaders = (headers: Record<string, string> | undefined) =>
|
|
42
|
+
Object.fromEntries(new Headers(headers).entries());
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Saves the request of an update check the server answered: the server it
|
|
46
|
+
* resolved, its headers and timeout, and its update strategy, which only a
|
|
47
|
+
* check knows. Only answered checks save it, so native always repeats a
|
|
48
|
+
* request that reached the server, whichever instance made it last, and a
|
|
49
|
+
* device that never checked sends nothing. Native checks of main save theirs
|
|
50
|
+
* the same way. The channel is left out on purpose: native checks
|
|
51
|
+
* the device's own channel, the one the crashing bundle came from and its fix
|
|
52
|
+
* is published to. A check of another channel is a one-off until its update
|
|
53
|
+
* is applied, and a crash must not switch the device's channel.
|
|
54
|
+
*/
|
|
55
|
+
export const saveRecoveryCheckConfig = (input: {
|
|
56
|
+
readonly baseURL: string;
|
|
57
|
+
readonly requestHeaders?: Record<string, string>;
|
|
58
|
+
readonly requestTimeout?: number;
|
|
59
|
+
readonly updateStrategy: CheckForUpdateOptions["updateStrategy"];
|
|
60
|
+
}) => {
|
|
61
|
+
write({
|
|
62
|
+
version: 1,
|
|
63
|
+
baseURL: input.baseURL,
|
|
64
|
+
requestHeaders: sentHeaders(input.requestHeaders),
|
|
65
|
+
requestTimeoutMs: input.requestTimeout ?? DEFAULT_REQUEST_TIMEOUT_MS,
|
|
66
|
+
updateStrategy: input.updateStrategy,
|
|
67
|
+
});
|
|
68
|
+
};
|
package/src/sdkVersion.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const HOT_UPDATER_SDK_VERSION = "1.1.
|
|
1
|
+
export const HOT_UPDATER_SDK_VERSION = "1.1.2";
|