react-native-update 10.48.3 → 10.49.0
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/BUNDLEHASH_MIGRATION.md +335 -0
- package/NATIVE_CHECKUPDATE_DESIGN.md +192 -0
- package/android/jni/Android.mk +1 -0
- package/android/lib/arm64-v8a/librnupdate.so +0 -0
- package/android/lib/armeabi-v7a/librnupdate.so +0 -0
- package/android/lib/x86/librnupdate.so +0 -0
- package/android/lib/x86_64/librnupdate.so +0 -0
- package/android/src/main/java/cn/reactnative/modules/update/UpdateContext.java +89 -0
- package/android/src/main/java/cn/reactnative/modules/update/UpdateModuleImpl.java +11 -0
- package/android/src/newarch/cn/reactnative/modules/update/UpdateModule.java +5 -0
- package/android/src/oldarch/cn/reactnative/modules/update/UpdateModule.java +5 -0
- package/cpp/patch_core/digest.cpp +177 -0
- package/cpp/patch_core/digest.h +43 -0
- package/cpp/patch_core/tests/patch_core_test.cpp +70 -0
- package/harmony/pushy/src/main/cpp/CMakeLists.txt +1 -0
- package/harmony/pushy/src/main/cpp/pushy.cpp +47 -0
- package/harmony/pushy/src/main/ets/NativePatchCore.ts +2 -0
- package/harmony/pushy/src/main/ets/PushyTurboModule.ts +11 -0
- package/harmony/pushy/src/main/ets/UpdateContext.ts +54 -0
- package/harmony/pushy.har +0 -0
- package/ios/RCTPushy/RCTPushy.mm +55 -0
- package/package.json +1 -1
- package/react-native-update.podspec +1 -0
- package/src/NativePushy.ts +6 -0
- package/src/client.ts +21 -3
- package/src/core.ts +27 -0
- package/src/locales/en.ts +2 -0
- package/src/locales/zh.ts +2 -0
- package/src/type.ts +29 -3
package/src/client.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
cInfo,
|
|
9
9
|
currentVersion,
|
|
10
10
|
currentVersionInfo,
|
|
11
|
+
getBundleHash,
|
|
11
12
|
isFirstTime,
|
|
12
13
|
isRolledBack,
|
|
13
14
|
PushyModule,
|
|
@@ -51,6 +52,7 @@ import {
|
|
|
51
52
|
noop,
|
|
52
53
|
promiseAny,
|
|
53
54
|
testUrls,
|
|
55
|
+
warn,
|
|
54
56
|
} from './utils';
|
|
55
57
|
|
|
56
58
|
/**
|
|
@@ -99,7 +101,7 @@ const excludeConfiguredEndpoints = (
|
|
|
99
101
|
|
|
100
102
|
assertWeb();
|
|
101
103
|
|
|
102
|
-
const
|
|
104
|
+
const createDefaultClientOptions = (): ClientOptions => ({
|
|
103
105
|
appKey: '',
|
|
104
106
|
autoMarkSuccess: true,
|
|
105
107
|
updateStrategy: __DEV__ ? 'alwaysAlert' : 'alertUpdateAndIgnoreError',
|
|
@@ -107,7 +109,7 @@ const defaultClientOptions: ClientOptions = {
|
|
|
107
109
|
logger: noop,
|
|
108
110
|
debug: false,
|
|
109
111
|
throwError: false,
|
|
110
|
-
};
|
|
112
|
+
});
|
|
111
113
|
|
|
112
114
|
export const sharedState: {
|
|
113
115
|
progressHandlers: Record<string, EmitterSubscription>;
|
|
@@ -145,7 +147,7 @@ const assertHash = (hash: string) => {
|
|
|
145
147
|
|
|
146
148
|
// for China users
|
|
147
149
|
export class Pushy {
|
|
148
|
-
options =
|
|
150
|
+
options: ClientOptions = createDefaultClientOptions();
|
|
149
151
|
clientType: 'Pushy' | 'Cresc' = 'Pushy';
|
|
150
152
|
lastChecking?: number;
|
|
151
153
|
lastRespJson?: Promise<CheckResult>;
|
|
@@ -591,6 +593,11 @@ export class Pushy {
|
|
|
591
593
|
this.notifyAfterCheckUpdate({ status: 'skipped' });
|
|
592
594
|
return;
|
|
593
595
|
}
|
|
596
|
+
// 内容寻址的二进制身份,服务端据此精确判定 pdiff 适用性(取代 buildTime
|
|
597
|
+
// 启发式)。同步读 core 里已预取的值:还没算完就省略字段(服务端回退
|
|
598
|
+
// buildTime 启发式),下一次检查自然带上——绝不为它 await、拖慢或复杂化
|
|
599
|
+
// 检查流程。
|
|
600
|
+
const bundleHash = __DEV__ ? '' : getBundleHash();
|
|
594
601
|
const now = Date.now();
|
|
595
602
|
if (
|
|
596
603
|
this.lastRespJson &&
|
|
@@ -620,6 +627,7 @@ export class Pushy {
|
|
|
620
627
|
cInfo,
|
|
621
628
|
// 可消费的 diff 轨道版本(2 = hdiffv2 轨道),服务端据此门控下发
|
|
622
629
|
...(supportedDiffVersion ? { diffV: supportedDiffVersion } : {}),
|
|
630
|
+
...(bundleHash ? { bundleHash } : {}),
|
|
623
631
|
...extra,
|
|
624
632
|
};
|
|
625
633
|
if (__DEV__) {
|
|
@@ -651,6 +659,16 @@ export class Pushy {
|
|
|
651
659
|
|
|
652
660
|
log('checking result:', result);
|
|
653
661
|
|
|
662
|
+
if (result?.bundleStatus === 'unknownBundle') {
|
|
663
|
+
// 服务端判定当前二进制内嵌 bundle 未注册,增量已被降级为全量。只面向
|
|
664
|
+
// 开发者(日志 + 遥测,控制台聚合是主渠道);终端用户无感知。
|
|
665
|
+
warn(this.t('warn_unknown_bundle'));
|
|
666
|
+
this.report({
|
|
667
|
+
type: 'bundleMismatch',
|
|
668
|
+
data: bundleHash ? { bundleHash } : {},
|
|
669
|
+
});
|
|
670
|
+
}
|
|
671
|
+
|
|
654
672
|
this.notifyAfterCheckUpdate({ status: 'completed', result });
|
|
655
673
|
return result;
|
|
656
674
|
} catch (e: any) {
|
package/src/core.ts
CHANGED
|
@@ -71,6 +71,33 @@ export const supportedDiffVersion: number =
|
|
|
71
71
|
PushyConstants.supportedDiffVersion || 0;
|
|
72
72
|
let uuid = PushyConstants.uuid;
|
|
73
73
|
|
|
74
|
+
// bundleHash = sha256 of the JS bundle embedded in the binary (the pdiff
|
|
75
|
+
// source). Content identity for the server's pdiff-applicability check,
|
|
76
|
+
// replacing the buildTime heuristic. Natively lazy-computed and cached;
|
|
77
|
+
// prefetched fire-and-forget at module load so the value is usually settled
|
|
78
|
+
// before the first checkUpdate builds its body. Until then (first install,
|
|
79
|
+
// slow device) getBundleHash returns '' and the field is simply omitted — the
|
|
80
|
+
// server falls back to the buildTime heuristic and the next check carries it.
|
|
81
|
+
// Deliberately synchronous at read time: checkUpdate must not await anything
|
|
82
|
+
// between its dedup window and the fetch, and a hash is never worth delaying
|
|
83
|
+
// a check for.
|
|
84
|
+
let bundleHash = '';
|
|
85
|
+
// The JS layer can arrive via hot update onto an older binary whose native
|
|
86
|
+
// module predates the method, hence the feature detect. On web PushyModule is
|
|
87
|
+
// a noop Proxy and the call settles to ''.
|
|
88
|
+
if (typeof PushyModule.getBundleHash === 'function') {
|
|
89
|
+
Promise.resolve(PushyModule.getBundleHash())
|
|
90
|
+
.then((hash: unknown) => {
|
|
91
|
+
bundleHash = String(hash || '');
|
|
92
|
+
})
|
|
93
|
+
.catch((e: any) => {
|
|
94
|
+
log('getBundleHash failed:', e?.message || e);
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** '' while unknown (not yet computed, debug build, no embedded bundle, older native). */
|
|
99
|
+
export const getBundleHash = (): string => bundleHash;
|
|
100
|
+
|
|
74
101
|
async function getLocalHashInfo(hash: string) {
|
|
75
102
|
return JSON.parse(await PushyModule.getLocalHashInfo(hash));
|
|
76
103
|
}
|
package/src/locales/en.ts
CHANGED
|
@@ -44,6 +44,8 @@ export default {
|
|
|
44
44
|
// Error messages
|
|
45
45
|
error_appkey_required: 'appKey is required',
|
|
46
46
|
error_parse_version_info: 'Failed to parse currentVersionInfo: {{info}}',
|
|
47
|
+
warn_unknown_bundle:
|
|
48
|
+
'The bundle embedded in this binary is not registered on the update platform; incremental updates are degraded to full downloads. Upload the package with pushy uploadIpa / uploadApk / uploadApp.',
|
|
47
49
|
error_update_check_failed: 'Update check failed',
|
|
48
50
|
error_cannot_connect_server:
|
|
49
51
|
'Can not connect to update server. Please check your network.',
|
package/src/locales/zh.ts
CHANGED
|
@@ -42,6 +42,8 @@ export default {
|
|
|
42
42
|
// Error messages
|
|
43
43
|
error_appkey_required: '需要提供 appKey',
|
|
44
44
|
error_parse_version_info: '解析 currentVersionInfo 失败: {{info}}',
|
|
45
|
+
warn_unknown_bundle:
|
|
46
|
+
'当前二进制内嵌 bundle 未在更新平台注册,增量更新已降级为全量。请使用 pushy uploadIpa / uploadApk / uploadApp 上传对应安装包。',
|
|
45
47
|
error_update_check_failed: '更新检查失败',
|
|
46
48
|
error_cannot_connect_server: '无法连接到更新服务器。请检查网络连接。',
|
|
47
49
|
error_cannot_connect_backup:
|
package/src/type.ts
CHANGED
|
@@ -17,15 +17,37 @@ export interface VersionInfo {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
interface RootResult {
|
|
20
|
-
upToDate?:
|
|
21
|
-
expired?:
|
|
20
|
+
upToDate?: boolean;
|
|
21
|
+
expired?: boolean;
|
|
22
22
|
downloadUrl?: string;
|
|
23
|
-
update?:
|
|
23
|
+
update?: boolean;
|
|
24
24
|
paused?: 'app' | 'package';
|
|
25
25
|
message?: string;
|
|
26
26
|
paths?: string[];
|
|
27
|
+
/**
|
|
28
|
+
* Server verdict on the reported bundleHash: 'matched' — the installed
|
|
29
|
+
* binary is registered; 'rebuiltSameJs' — repackaged binary with identical
|
|
30
|
+
* JS (no upload needed); 'unknownBundle' — unregistered binary, incremental
|
|
31
|
+
* updates degraded to full downloads until the package is uploaded.
|
|
32
|
+
*/
|
|
33
|
+
bundleStatus?: 'matched' | 'rebuiltSameJs' | 'unknownBundle';
|
|
27
34
|
}
|
|
28
35
|
|
|
36
|
+
export type UpToDateCheckResult = RootResult & {
|
|
37
|
+
upToDate: true;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export type UpdateAvailableCheckResult = RootResult &
|
|
41
|
+
Partial<VersionInfo> & {
|
|
42
|
+
update: true;
|
|
43
|
+
expVersion?: VersionInfo;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export type ExpiredCheckResult = RootResult & {
|
|
47
|
+
expired: true;
|
|
48
|
+
downloadUrl: string;
|
|
49
|
+
};
|
|
50
|
+
|
|
29
51
|
export type CheckResult = RootResult &
|
|
30
52
|
Partial<VersionInfo> & {
|
|
31
53
|
expVersion?: VersionInfo;
|
|
@@ -57,6 +79,10 @@ export type EventType =
|
|
|
57
79
|
| 'errorMarkSuccess'
|
|
58
80
|
| 'reset'
|
|
59
81
|
| 'errorReset'
|
|
82
|
+
// Server reported bundleStatus: unknownBundle — the installed binary is not
|
|
83
|
+
// registered on the update platform (developer-facing only, local logger;
|
|
84
|
+
// not a server telemetry event).
|
|
85
|
+
| 'bundleMismatch'
|
|
60
86
|
| 'errorRestart'
|
|
61
87
|
| 'errorSwitchVersion'
|
|
62
88
|
| 'downloadingApk'
|