@hot-updater/react-native 0.36.7 → 1.0.0-rc.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/android/src/main/java/com/hotupdater/BundleFileStorageService.kt +357 -6
- package/android/src/main/java/com/hotupdater/BundleMetadata.kt +268 -34
- package/android/src/main/java/com/hotupdater/HotUpdaterImpl.kt +75 -9
- package/android/src/main/java/com/hotupdater/NativeConfigUtils.kt +2 -16
- package/android/src/main/java/com/hotupdater/ReleaseCatalogCacheService.kt +166 -0
- package/android/src/main/java/com/hotupdater/SignatureVerifier.kt +1 -2
- package/android/src/newarch/HotUpdater.kt +1 -1
- package/android/src/newarch/HotUpdaterModule.kt +116 -0
- package/android/src/oldarch/HotUpdater.kt +1 -1
- package/android/src/oldarch/HotUpdaterModule.kt +128 -0
- package/android/src/oldarch/HotUpdaterSpec.kt +38 -0
- package/android/src/test/java/com/hotupdater/BundleFileStorageServiceTest.kt +280 -2
- package/android/src/test/java/com/hotupdater/HotUpdaterImplTest.kt +57 -2
- package/android/src/test/java/com/hotupdater/ReleaseCatalogCacheServiceTest.kt +118 -0
- package/ios/HotUpdater/Internal/BundleFileStorageService.swift +491 -30
- package/ios/HotUpdater/Internal/BundleMetadata.swift +229 -6
- package/ios/HotUpdater/Internal/HotUpdater.mm +122 -0
- package/ios/HotUpdater/Internal/HotUpdaterImpl.swift +176 -7
- package/ios/HotUpdater/Internal/ReleaseCatalogCacheService.swift +213 -0
- package/lib/commonjs/catalogCacheNative.js +44 -0
- package/lib/commonjs/catalogCacheNative.js.map +1 -0
- package/lib/commonjs/catalogCacheNative.spec.js +31 -0
- package/lib/commonjs/catalogCacheNative.spec.js.map +1 -0
- package/lib/commonjs/checkForUpdate.js +231 -60
- package/lib/commonjs/checkForUpdate.js.map +1 -1
- package/lib/commonjs/checkForUpdate.releaseCatalog.spec.js +604 -0
- package/lib/commonjs/checkForUpdate.releaseCatalog.spec.js.map +1 -0
- package/lib/commonjs/error.js +8 -1
- package/lib/commonjs/error.js.map +1 -1
- package/lib/commonjs/{fetchUpdateInfo.js → fetchJSON.js} +11 -14
- package/lib/commonjs/fetchJSON.js.map +1 -0
- package/lib/commonjs/httpClient.js +153 -0
- package/lib/commonjs/httpClient.js.map +1 -0
- package/lib/commonjs/httpClient.spec.js +102 -0
- package/lib/commonjs/httpClient.spec.js.map +1 -0
- package/lib/commonjs/index.js +48 -71
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/index.spec.js +117 -161
- package/lib/commonjs/index.spec.js.map +1 -1
- package/lib/commonjs/iosInterop.spec.js +18 -0
- package/lib/commonjs/iosInterop.spec.js.map +1 -0
- package/lib/commonjs/native.js +222 -55
- package/lib/commonjs/native.js.map +1 -1
- package/lib/commonjs/native.spec.js +226 -12
- package/lib/commonjs/native.spec.js.map +1 -1
- package/lib/commonjs/notifyAppReadyAnalytics.boundary.spec.js +218 -0
- package/lib/commonjs/notifyAppReadyAnalytics.boundary.spec.js.map +1 -0
- package/lib/commonjs/notifyAppReadyAnalytics.js +133 -0
- package/lib/commonjs/notifyAppReadyAnalytics.js.map +1 -0
- package/lib/commonjs/notifyAppReadyAnalytics.spec.js +246 -0
- package/lib/commonjs/notifyAppReadyAnalytics.spec.js.map +1 -0
- package/lib/commonjs/notifyAppReadyAnalytics.test-utils.js +24 -0
- package/lib/commonjs/notifyAppReadyAnalytics.test-utils.js.map +1 -0
- package/lib/commonjs/notifyAppReadyAnalytics.transport.spec.js +117 -0
- package/lib/commonjs/notifyAppReadyAnalytics.transport.spec.js.map +1 -0
- package/lib/commonjs/releaseCatalogCache.js +179 -0
- package/lib/commonjs/releaseCatalogCache.js.map +1 -0
- package/lib/commonjs/releaseCatalogCache.spec.js +195 -0
- package/lib/commonjs/releaseCatalogCache.spec.js.map +1 -0
- package/lib/commonjs/releaseCatalogCacheNativeContract.spec.js +64 -0
- package/lib/commonjs/releaseCatalogCacheNativeContract.spec.js.map +1 -0
- package/lib/commonjs/sdkVersion.js +1 -1
- package/lib/commonjs/sdkVersion.js.map +1 -1
- package/lib/commonjs/specs/NativeHotUpdater.js.map +1 -1
- package/lib/commonjs/types.js +0 -12
- package/lib/commonjs/types.js.map +1 -1
- package/lib/commonjs/wrap.js +7 -82
- package/lib/commonjs/wrap.js.map +1 -1
- package/lib/commonjs/wrap.spec.js +203 -56
- package/lib/commonjs/wrap.spec.js.map +1 -1
- package/lib/commonjs/wrap.types.js +6 -0
- package/lib/commonjs/wrap.types.js.map +1 -0
- package/lib/module/catalogCacheNative.js +36 -0
- package/lib/module/catalogCacheNative.js.map +1 -0
- package/lib/module/catalogCacheNative.spec.js +31 -0
- package/lib/module/catalogCacheNative.spec.js.map +1 -0
- package/lib/module/checkForUpdate.js +233 -62
- package/lib/module/checkForUpdate.js.map +1 -1
- package/lib/module/checkForUpdate.releaseCatalog.spec.js +603 -0
- package/lib/module/checkForUpdate.releaseCatalog.spec.js.map +1 -0
- package/lib/module/error.js +6 -0
- package/lib/module/error.js.map +1 -1
- package/lib/module/{fetchUpdateInfo.js → fetchJSON.js} +9 -12
- package/lib/module/fetchJSON.js.map +1 -0
- package/lib/module/httpClient.js +148 -0
- package/lib/module/httpClient.js.map +1 -0
- package/lib/module/httpClient.spec.js +102 -0
- package/lib/module/httpClient.spec.js.map +1 -0
- package/lib/module/index.js +49 -66
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.spec.js +117 -161
- package/lib/module/index.spec.js.map +1 -1
- package/lib/module/iosInterop.spec.js +18 -0
- package/lib/module/iosInterop.spec.js.map +1 -0
- package/lib/module/native.js +206 -51
- package/lib/module/native.js.map +1 -1
- package/lib/module/native.spec.js +226 -12
- package/lib/module/native.spec.js.map +1 -1
- package/lib/module/notifyAppReadyAnalytics.boundary.spec.js +217 -0
- package/lib/module/notifyAppReadyAnalytics.boundary.spec.js.map +1 -0
- package/lib/module/notifyAppReadyAnalytics.js +128 -0
- package/lib/module/notifyAppReadyAnalytics.js.map +1 -0
- package/lib/module/notifyAppReadyAnalytics.spec.js +245 -0
- package/lib/module/notifyAppReadyAnalytics.spec.js.map +1 -0
- package/lib/module/notifyAppReadyAnalytics.test-utils.js +18 -0
- package/lib/module/notifyAppReadyAnalytics.test-utils.js.map +1 -0
- package/lib/module/notifyAppReadyAnalytics.transport.spec.js +116 -0
- package/lib/module/notifyAppReadyAnalytics.transport.spec.js.map +1 -0
- package/lib/module/releaseCatalogCache.js +171 -0
- package/lib/module/releaseCatalogCache.js.map +1 -0
- package/lib/module/releaseCatalogCache.spec.js +195 -0
- package/lib/module/releaseCatalogCache.spec.js.map +1 -0
- package/lib/module/releaseCatalogCacheNativeContract.spec.js +64 -0
- package/lib/module/releaseCatalogCacheNativeContract.spec.js.map +1 -0
- package/lib/module/sdkVersion.js +1 -1
- package/lib/module/sdkVersion.js.map +1 -1
- package/lib/module/specs/NativeHotUpdater.js.map +1 -1
- package/lib/module/types.js +0 -12
- package/lib/module/types.js.map +1 -1
- package/lib/module/wrap.js +6 -81
- package/lib/module/wrap.js.map +1 -1
- package/lib/module/wrap.spec.js +203 -56
- package/lib/module/wrap.spec.js.map +1 -1
- package/lib/module/wrap.types.js +4 -0
- package/lib/module/wrap.types.js.map +1 -0
- package/lib/typescript/commonjs/catalogCacheNative.d.ts +4 -0
- package/lib/typescript/commonjs/catalogCacheNative.d.ts.map +1 -0
- package/lib/typescript/commonjs/checkForUpdate.d.ts +14 -4
- package/lib/typescript/commonjs/checkForUpdate.d.ts.map +1 -1
- package/lib/typescript/commonjs/error.d.ts +3 -0
- package/lib/typescript/commonjs/error.d.ts.map +1 -1
- package/lib/typescript/commonjs/fetchJSON.d.ts +6 -0
- package/lib/typescript/commonjs/fetchJSON.d.ts.map +1 -0
- package/lib/typescript/commonjs/httpClient.d.ts +56 -0
- package/lib/typescript/commonjs/httpClient.d.ts.map +1 -0
- package/lib/typescript/commonjs/index.d.ts +32 -41
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/native.d.ts +83 -18
- package/lib/typescript/commonjs/native.d.ts.map +1 -1
- package/lib/typescript/commonjs/notifyAppReadyAnalytics.d.ts +13 -0
- package/lib/typescript/commonjs/notifyAppReadyAnalytics.d.ts.map +1 -0
- package/lib/typescript/commonjs/notifyAppReadyAnalytics.test-utils.d.ts +8 -0
- package/lib/typescript/commonjs/notifyAppReadyAnalytics.test-utils.d.ts.map +1 -0
- package/lib/typescript/commonjs/releaseCatalogCache.d.ts +25 -0
- package/lib/typescript/commonjs/releaseCatalogCache.d.ts.map +1 -0
- package/lib/typescript/commonjs/sdkVersion.d.ts +1 -1
- package/lib/typescript/commonjs/sdkVersion.d.ts.map +1 -1
- package/lib/typescript/commonjs/specs/NativeHotUpdater.d.ts +40 -5
- package/lib/typescript/commonjs/specs/NativeHotUpdater.d.ts.map +1 -1
- package/lib/typescript/commonjs/types.d.ts +0 -118
- package/lib/typescript/commonjs/types.d.ts.map +1 -1
- package/lib/typescript/commonjs/wrap.d.ts +2 -191
- package/lib/typescript/commonjs/wrap.d.ts.map +1 -1
- package/lib/typescript/commonjs/wrap.types.d.ts +65 -0
- package/lib/typescript/commonjs/wrap.types.d.ts.map +1 -0
- package/lib/typescript/module/catalogCacheNative.d.ts +4 -0
- package/lib/typescript/module/catalogCacheNative.d.ts.map +1 -0
- package/lib/typescript/module/checkForUpdate.d.ts +14 -4
- package/lib/typescript/module/checkForUpdate.d.ts.map +1 -1
- package/lib/typescript/module/error.d.ts +3 -0
- package/lib/typescript/module/error.d.ts.map +1 -1
- package/lib/typescript/module/fetchJSON.d.ts +6 -0
- package/lib/typescript/module/fetchJSON.d.ts.map +1 -0
- package/lib/typescript/module/httpClient.d.ts +56 -0
- package/lib/typescript/module/httpClient.d.ts.map +1 -0
- package/lib/typescript/module/index.d.ts +32 -41
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/native.d.ts +83 -18
- package/lib/typescript/module/native.d.ts.map +1 -1
- package/lib/typescript/module/notifyAppReadyAnalytics.d.ts +13 -0
- package/lib/typescript/module/notifyAppReadyAnalytics.d.ts.map +1 -0
- package/lib/typescript/module/notifyAppReadyAnalytics.test-utils.d.ts +8 -0
- package/lib/typescript/module/notifyAppReadyAnalytics.test-utils.d.ts.map +1 -0
- package/lib/typescript/module/releaseCatalogCache.d.ts +25 -0
- package/lib/typescript/module/releaseCatalogCache.d.ts.map +1 -0
- package/lib/typescript/module/sdkVersion.d.ts +1 -1
- package/lib/typescript/module/sdkVersion.d.ts.map +1 -1
- package/lib/typescript/module/specs/NativeHotUpdater.d.ts +40 -5
- package/lib/typescript/module/specs/NativeHotUpdater.d.ts.map +1 -1
- package/lib/typescript/module/types.d.ts +0 -118
- package/lib/typescript/module/types.d.ts.map +1 -1
- package/lib/typescript/module/wrap.d.ts +2 -191
- package/lib/typescript/module/wrap.d.ts.map +1 -1
- package/lib/typescript/module/wrap.types.d.ts +65 -0
- package/lib/typescript/module/wrap.types.d.ts.map +1 -0
- package/package.json +6 -24
- package/src/catalogCacheNative.spec.ts +63 -0
- package/src/catalogCacheNative.ts +74 -0
- package/src/checkForUpdate.releaseCatalog.spec.ts +596 -0
- package/src/checkForUpdate.ts +368 -97
- package/src/error.ts +7 -0
- package/src/{fetchUpdateInfo.ts → fetchJSON.ts} +8 -15
- package/src/httpClient.spec.ts +132 -0
- package/src/httpClient.ts +261 -0
- package/src/index.spec.ts +110 -203
- package/src/index.ts +70 -93
- package/src/iosInterop.spec.ts +30 -0
- package/src/native.spec.ts +226 -10
- package/src/native.ts +385 -83
- package/src/notifyAppReadyAnalytics.boundary.spec.ts +234 -0
- package/src/notifyAppReadyAnalytics.spec.ts +243 -0
- package/src/notifyAppReadyAnalytics.test-utils.ts +31 -0
- package/src/notifyAppReadyAnalytics.transport.spec.ts +130 -0
- package/src/notifyAppReadyAnalytics.ts +194 -0
- package/src/releaseCatalogCache.spec.ts +282 -0
- package/src/releaseCatalogCache.ts +341 -0
- package/src/releaseCatalogCacheNativeContract.spec.ts +80 -0
- package/src/sdkVersion.ts +1 -1
- package/src/specs/NativeHotUpdater.ts +51 -5
- package/src/types.ts +0 -140
- package/src/wrap.spec.ts +251 -56
- package/src/wrap.tsx +23 -318
- package/src/wrap.types.ts +78 -0
- package/android/src/main/java/com/hotupdater/StringResourceUtils.kt +0 -45
- package/app.plugin.js +0 -1
- package/ios/HotUpdater/Internal/HotUpdaterCrashHandler.h +0 -7
- package/ios/HotUpdater/Internal/HotUpdaterCrashHandler.mm +0 -4
- package/lib/commonjs/DefaultResolver.js +0 -50
- package/lib/commonjs/DefaultResolver.js.map +0 -1
- package/lib/commonjs/DefaultResolver.spec.js +0 -144
- package/lib/commonjs/DefaultResolver.spec.js.map +0 -1
- package/lib/commonjs/fetchUpdateInfo.js.map +0 -1
- package/lib/module/DefaultResolver.js +0 -46
- package/lib/module/DefaultResolver.js.map +0 -1
- package/lib/module/DefaultResolver.spec.js +0 -144
- package/lib/module/DefaultResolver.spec.js.map +0 -1
- package/lib/module/fetchUpdateInfo.js.map +0 -1
- package/lib/typescript/commonjs/DefaultResolver.d.ts +0 -11
- package/lib/typescript/commonjs/DefaultResolver.d.ts.map +0 -1
- package/lib/typescript/commonjs/fetchUpdateInfo.d.ts +0 -7
- package/lib/typescript/commonjs/fetchUpdateInfo.d.ts.map +0 -1
- package/lib/typescript/module/DefaultResolver.d.ts +0 -11
- package/lib/typescript/module/DefaultResolver.d.ts.map +0 -1
- package/lib/typescript/module/fetchUpdateInfo.d.ts +0 -7
- package/lib/typescript/module/fetchUpdateInfo.d.ts.map +0 -1
- package/plugin/build/transformers.js +0 -314
- package/plugin/build/withHotUpdater.js +0 -228
- package/src/DefaultResolver.spec.ts +0 -193
- package/src/DefaultResolver.ts +0 -63
|
@@ -1,314 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Pure transformation functions for HotUpdater code injection
|
|
4
|
-
* These utilities handle code transformations for different React Native patterns
|
|
5
|
-
*/
|
|
6
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.transformAndroid = transformAndroid;
|
|
8
|
-
exports.transformIOS = transformIOS;
|
|
9
|
-
function findMatchingClosingParen(source, openParenIndex) {
|
|
10
|
-
let depth = 0;
|
|
11
|
-
for (let i = openParenIndex; i < source.length; i += 1) {
|
|
12
|
-
const char = source[i];
|
|
13
|
-
if (char === "(") {
|
|
14
|
-
depth += 1;
|
|
15
|
-
continue;
|
|
16
|
-
}
|
|
17
|
-
if (char === ")") {
|
|
18
|
-
depth -= 1;
|
|
19
|
-
if (depth === 0) {
|
|
20
|
-
return i;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
return -1;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Helper to add lines if they don't exist, anchored by a specific string.
|
|
28
|
-
*/
|
|
29
|
-
function addLinesOnce(contents, anchor, linesToAdd) {
|
|
30
|
-
if (linesToAdd.every((line) => contents.includes(line))) {
|
|
31
|
-
// All lines already exist, do nothing
|
|
32
|
-
return contents;
|
|
33
|
-
}
|
|
34
|
-
// Check if the anchor exists
|
|
35
|
-
if (!contents.includes(anchor)) {
|
|
36
|
-
// Anchor not found, cannot add lines reliably.
|
|
37
|
-
return contents;
|
|
38
|
-
}
|
|
39
|
-
// Add lines after the anchor
|
|
40
|
-
return contents.replace(anchor, `${anchor}\n${linesToAdd.join("\n")}`);
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Android: handle getDefaultReactHost pattern (RN 0.82+ style).
|
|
44
|
-
* Adds jsBundleFilePath parameter to the call.
|
|
45
|
-
*/
|
|
46
|
-
function transformAndroidReactHost(contents) {
|
|
47
|
-
const kotlinImport = "import com.hotupdater.HotUpdater";
|
|
48
|
-
const kotlinImportAnchor = "import com.facebook.react.ReactApplication";
|
|
49
|
-
// Quick pattern detection: only touch files using getDefaultReactHost
|
|
50
|
-
// with the new RN 0.82+ parameter style.
|
|
51
|
-
if (!contents.includes("getDefaultReactHost(") ||
|
|
52
|
-
!contents.includes("packageList =")) {
|
|
53
|
-
return contents;
|
|
54
|
-
}
|
|
55
|
-
// 1. Ensure HotUpdater import exists (idempotent via addLinesOnce)
|
|
56
|
-
const result = addLinesOnce(contents, kotlinImportAnchor, [kotlinImport]);
|
|
57
|
-
const callNeedle = "getDefaultReactHost(";
|
|
58
|
-
const callStartIndex = result.indexOf(callNeedle);
|
|
59
|
-
if (callStartIndex === -1) {
|
|
60
|
-
return result;
|
|
61
|
-
}
|
|
62
|
-
const openParenIndex = callStartIndex + callNeedle.length - 1;
|
|
63
|
-
const closeParenIndex = findMatchingClosingParen(result, openParenIndex);
|
|
64
|
-
if (closeParenIndex === -1) {
|
|
65
|
-
return result;
|
|
66
|
-
}
|
|
67
|
-
const callContents = result.slice(callStartIndex, closeParenIndex + 1);
|
|
68
|
-
const kotlinLegacyBundlePathRegex = /^([ \t]*)jsBundleFilePath = HotUpdater\.getJSBundleFile\(applicationContext\),[ \t]*\r?$/m;
|
|
69
|
-
const legacyBundlePathMatch = callContents.match(kotlinLegacyBundlePathRegex);
|
|
70
|
-
if (legacyBundlePathMatch) {
|
|
71
|
-
const paramIndent = legacyBundlePathMatch[1];
|
|
72
|
-
const jsBundleLines = [
|
|
73
|
-
`${paramIndent}jsBundleFilePath = if (BuildConfig.DEBUG) {`,
|
|
74
|
-
`${paramIndent} null`,
|
|
75
|
-
`${paramIndent}} else {`,
|
|
76
|
-
`${paramIndent} HotUpdater.getJSBundleFile(applicationContext)`,
|
|
77
|
-
`${paramIndent}},`,
|
|
78
|
-
];
|
|
79
|
-
const migratedCallContents = callContents.replace(kotlinLegacyBundlePathRegex, jsBundleLines.join("\n"));
|
|
80
|
-
return `${result.slice(0, callStartIndex)}${migratedCallContents}${result.slice(closeParenIndex + 1)}`;
|
|
81
|
-
}
|
|
82
|
-
if (callContents.includes("jsBundleFilePath")) {
|
|
83
|
-
return result;
|
|
84
|
-
}
|
|
85
|
-
const callLines = callContents.split("\n");
|
|
86
|
-
// Determine the indentation used for parameters (e.g. " ")
|
|
87
|
-
let paramIndent = "";
|
|
88
|
-
for (let i = 1; i < callLines.length; i += 1) {
|
|
89
|
-
const line = callLines[i];
|
|
90
|
-
const trimmed = line.trim();
|
|
91
|
-
if (trimmed.length === 0) {
|
|
92
|
-
continue;
|
|
93
|
-
}
|
|
94
|
-
if (trimmed.startsWith(")")) {
|
|
95
|
-
// No parameters detected, give up safely.
|
|
96
|
-
return result;
|
|
97
|
-
}
|
|
98
|
-
const indentMatch = line.match(/^(\s*)/);
|
|
99
|
-
paramIndent = indentMatch ? indentMatch[1] : "";
|
|
100
|
-
break;
|
|
101
|
-
}
|
|
102
|
-
if (!paramIndent) {
|
|
103
|
-
return result;
|
|
104
|
-
}
|
|
105
|
-
const closingLineStartIndex = result.lastIndexOf("\n", closeParenIndex);
|
|
106
|
-
const insertionIndex = closingLineStartIndex === -1 ? 0 : closingLineStartIndex + 1;
|
|
107
|
-
let prefix = result.slice(0, insertionIndex);
|
|
108
|
-
const suffix = result.slice(insertionIndex);
|
|
109
|
-
let prevNonWhitespaceIndex = prefix.length - 1;
|
|
110
|
-
while (prevNonWhitespaceIndex >= 0 &&
|
|
111
|
-
/\s/.test(prefix[prevNonWhitespaceIndex])) {
|
|
112
|
-
prevNonWhitespaceIndex -= 1;
|
|
113
|
-
}
|
|
114
|
-
if (prevNonWhitespaceIndex >= 0 &&
|
|
115
|
-
prefix[prevNonWhitespaceIndex] !== "," &&
|
|
116
|
-
prefix[prevNonWhitespaceIndex] !== "(") {
|
|
117
|
-
prefix = `${prefix.slice(0, prevNonWhitespaceIndex + 1)},${prefix.slice(prevNonWhitespaceIndex + 1)}`;
|
|
118
|
-
}
|
|
119
|
-
const jsBundleLines = [
|
|
120
|
-
`${paramIndent}jsBundleFilePath = if (BuildConfig.DEBUG) {`,
|
|
121
|
-
`${paramIndent} null`,
|
|
122
|
-
`${paramIndent}} else {`,
|
|
123
|
-
`${paramIndent} HotUpdater.getJSBundleFile(applicationContext)`,
|
|
124
|
-
`${paramIndent}},`,
|
|
125
|
-
];
|
|
126
|
-
return `${prefix}${jsBundleLines.join("\n")}\n${suffix}`;
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
* Android: DefaultReactNativeHost pattern (RN 0.81 / Expo 54).
|
|
130
|
-
* Adds getJSBundleFile() override to the host.
|
|
131
|
-
*/
|
|
132
|
-
function transformAndroidDefaultHost(contents) {
|
|
133
|
-
const kotlinImport = "import com.hotupdater.HotUpdater";
|
|
134
|
-
const kotlinImportAnchor = "import com.facebook.react.ReactApplication";
|
|
135
|
-
const kotlinReactNativeHostAnchor = "object : DefaultReactNativeHost(this) {";
|
|
136
|
-
const kotlinMethodCheck = "HotUpdater.getJSBundleFile(applicationContext)";
|
|
137
|
-
const kotlinLegacyMethodRegex = /^([ \t]*)override fun getJSBundleFile\(\): String\? \{[ \t]*\r?\n([ \t]*)return HotUpdater\.getJSBundleFile\(applicationContext\)[ \t]*\r?\n\1\}[ \t]*$/m;
|
|
138
|
-
const kotlinExistingMethodRegex = /^\s*override fun getJSBundleFile\(\): String\?\s*\{[\s\S]*?^\s*\}/gm;
|
|
139
|
-
const kotlinHermesAnchor = "override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED";
|
|
140
|
-
const kotlinNewArchAnchor = "override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED";
|
|
141
|
-
// Check if this is the old pattern with DefaultReactNativeHost
|
|
142
|
-
if (!contents.includes(kotlinReactNativeHostAnchor)) {
|
|
143
|
-
return contents;
|
|
144
|
-
}
|
|
145
|
-
// 1. Add import if missing
|
|
146
|
-
let result = addLinesOnce(contents, kotlinImportAnchor, [kotlinImport]);
|
|
147
|
-
const legacyMethodMatch = result.match(kotlinLegacyMethodRegex);
|
|
148
|
-
if (legacyMethodMatch) {
|
|
149
|
-
const methodIndent = legacyMethodMatch[1];
|
|
150
|
-
const bodyIndent = legacyMethodMatch[2];
|
|
151
|
-
const methodLines = [
|
|
152
|
-
`${methodIndent}override fun getJSBundleFile(): String? {`,
|
|
153
|
-
`${bodyIndent}return if (BuildConfig.DEBUG) {`,
|
|
154
|
-
`${bodyIndent} null`,
|
|
155
|
-
`${bodyIndent}} else {`,
|
|
156
|
-
`${bodyIndent} HotUpdater.getJSBundleFile(applicationContext)`,
|
|
157
|
-
`${bodyIndent}}`,
|
|
158
|
-
`${methodIndent}}`,
|
|
159
|
-
];
|
|
160
|
-
result = result.replace(kotlinLegacyMethodRegex, methodLines.join("\n"));
|
|
161
|
-
}
|
|
162
|
-
// 2. Add/Replace getJSBundleFile method if needed
|
|
163
|
-
if (!result.includes(kotlinMethodCheck)) {
|
|
164
|
-
// Remove potentially existing (different) override first
|
|
165
|
-
result = result.replace(kotlinExistingMethodRegex, "");
|
|
166
|
-
const lines = result.split("\n");
|
|
167
|
-
const findLineIndex = (needle) => {
|
|
168
|
-
for (let i = 0; i < lines.length; i += 1) {
|
|
169
|
-
if (lines[i].includes(needle)) {
|
|
170
|
-
return i;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
return -1;
|
|
174
|
-
};
|
|
175
|
-
// Prefer inserting after Hermes line, then after new architecture line
|
|
176
|
-
let anchorIndex = findLineIndex(kotlinHermesAnchor);
|
|
177
|
-
if (anchorIndex === -1) {
|
|
178
|
-
anchorIndex = findLineIndex(kotlinNewArchAnchor);
|
|
179
|
-
}
|
|
180
|
-
if (anchorIndex !== -1) {
|
|
181
|
-
const indentMatch = lines[anchorIndex].match(/^\s*/);
|
|
182
|
-
const indent = indentMatch ? indentMatch[0] : "";
|
|
183
|
-
const objectLine = lines.find((line) => line.includes("object : DefaultReactNativeHost"));
|
|
184
|
-
let indentSize = 2;
|
|
185
|
-
if (objectLine) {
|
|
186
|
-
const objectIndent = (objectLine.match(/^\s*/)?.[0] || "").length;
|
|
187
|
-
const propertyIndent = indent.length;
|
|
188
|
-
const diff = propertyIndent - objectIndent;
|
|
189
|
-
if (diff > 0) {
|
|
190
|
-
indentSize = diff;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
const spaces = indentSize === 2 ? " " : " ";
|
|
194
|
-
const bodyIndent = indent + spaces;
|
|
195
|
-
const methodLines = [
|
|
196
|
-
"", // blank line
|
|
197
|
-
`${indent}override fun getJSBundleFile(): String? {`,
|
|
198
|
-
`${bodyIndent}return if (BuildConfig.DEBUG) {`,
|
|
199
|
-
`${bodyIndent} null`,
|
|
200
|
-
`${bodyIndent}} else {`,
|
|
201
|
-
`${bodyIndent} HotUpdater.getJSBundleFile(applicationContext)`,
|
|
202
|
-
`${bodyIndent}}`,
|
|
203
|
-
`${indent}}`,
|
|
204
|
-
];
|
|
205
|
-
const insertIndex = anchorIndex + 1;
|
|
206
|
-
lines.splice(insertIndex, 0, ...methodLines);
|
|
207
|
-
result = lines.join("\n");
|
|
208
|
-
}
|
|
209
|
-
else {
|
|
210
|
-
// Fallback: insert before the closing brace of the object block
|
|
211
|
-
const hostStartIndex = lines.findIndex((line) => line.includes("object : DefaultReactNativeHost"));
|
|
212
|
-
if (hostStartIndex === -1) {
|
|
213
|
-
throw new Error("[transformAndroidDefaultHost] Could not find DefaultReactNativeHost block.");
|
|
214
|
-
}
|
|
215
|
-
let hostEndIndex = -1;
|
|
216
|
-
for (let i = lines.length - 1; i > hostStartIndex; i -= 1) {
|
|
217
|
-
if (lines[i].trim() === "}") {
|
|
218
|
-
hostEndIndex = i;
|
|
219
|
-
break;
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
if (hostEndIndex === -1) {
|
|
223
|
-
throw new Error("[transformAndroidDefaultHost] Could not find end of DefaultReactNativeHost block.");
|
|
224
|
-
}
|
|
225
|
-
const indentMatch = lines[hostEndIndex].match(/^\s*/);
|
|
226
|
-
const indent = indentMatch ? indentMatch[0] : "";
|
|
227
|
-
const bodyIndent = `${indent} `;
|
|
228
|
-
const methodLines = [
|
|
229
|
-
`${indent}override fun getJSBundleFile(): String? {`,
|
|
230
|
-
`${bodyIndent}return if (BuildConfig.DEBUG) {`,
|
|
231
|
-
`${bodyIndent} null`,
|
|
232
|
-
`${bodyIndent}} else {`,
|
|
233
|
-
`${bodyIndent} HotUpdater.getJSBundleFile(applicationContext)`,
|
|
234
|
-
`${bodyIndent}}`,
|
|
235
|
-
`${indent}}`,
|
|
236
|
-
];
|
|
237
|
-
lines.splice(hostEndIndex, 0, ...methodLines);
|
|
238
|
-
result = lines.join("\n");
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
return result;
|
|
242
|
-
}
|
|
243
|
-
/**
|
|
244
|
-
* Public Android transformer that applies all Android-specific transforms.
|
|
245
|
-
*/
|
|
246
|
-
function transformAndroid(contents) {
|
|
247
|
-
let result = contents;
|
|
248
|
-
result = transformAndroidReactHost(result);
|
|
249
|
-
result = transformAndroidDefaultHost(result);
|
|
250
|
-
return result;
|
|
251
|
-
}
|
|
252
|
-
/**
|
|
253
|
-
* iOS: Objective-C AppDelegate transformation.
|
|
254
|
-
* Replaces NSBundle-based bundleURL with HotUpdater bundleURL.
|
|
255
|
-
*/
|
|
256
|
-
function transformIOSObjC(contents) {
|
|
257
|
-
const iosImport = "#import <HotUpdater/HotUpdater.h>";
|
|
258
|
-
const iosBundleUrl = "[HotUpdater bundleURL]";
|
|
259
|
-
const iosOriginalBundleUrlRegex = /\[\[NSBundle mainBundle\] URLForResource:@"main" withExtension:@"jsbundle"\]/g;
|
|
260
|
-
const iosAppDelegateHeader = '#import "AppDelegate.h"';
|
|
261
|
-
// Check if it's likely Obj-C
|
|
262
|
-
if (!contents.includes(iosAppDelegateHeader)) {
|
|
263
|
-
return contents;
|
|
264
|
-
}
|
|
265
|
-
let result = contents;
|
|
266
|
-
// 1. Ensure HotUpdater import is present
|
|
267
|
-
if (!result.includes(iosImport)) {
|
|
268
|
-
result = addLinesOnce(result, iosAppDelegateHeader, [iosImport]);
|
|
269
|
-
}
|
|
270
|
-
// 2. Swap NSBundle-based URL with HotUpdater bundleURL, but only once
|
|
271
|
-
if (!result.includes(iosBundleUrl) &&
|
|
272
|
-
iosOriginalBundleUrlRegex.test(result)) {
|
|
273
|
-
result = result.replace(iosOriginalBundleUrlRegex, iosBundleUrl);
|
|
274
|
-
}
|
|
275
|
-
return result;
|
|
276
|
-
}
|
|
277
|
-
/**
|
|
278
|
-
* iOS: Swift / Expo AppDelegate transformation.
|
|
279
|
-
* Replaces Bundle.main.url-based bundleURL with HotUpdater.bundleURL().
|
|
280
|
-
*/
|
|
281
|
-
function transformIOSSwift(contents) {
|
|
282
|
-
const swiftImport = "import HotUpdater";
|
|
283
|
-
const swiftBundleUrl = "HotUpdater.bundleURL()";
|
|
284
|
-
const swiftOriginalBundleUrlRegex = /Bundle\.main\.url\(forResource: "?main"?, withExtension: "jsbundle"\)/g;
|
|
285
|
-
// Check if it's likely Swift AppDelegate code
|
|
286
|
-
if (!contents.includes("import ")) {
|
|
287
|
-
return contents;
|
|
288
|
-
}
|
|
289
|
-
// 1. Add import if missing - find the last import statement and add after it
|
|
290
|
-
let result = contents;
|
|
291
|
-
if (!result.includes(swiftImport)) {
|
|
292
|
-
// Find the last import statement
|
|
293
|
-
const lastImportMatch = result.match(/^import .*$/gm);
|
|
294
|
-
if (lastImportMatch) {
|
|
295
|
-
const lastImport = lastImportMatch[lastImportMatch.length - 1];
|
|
296
|
-
result = result.replace(lastImport, `${lastImport}\n${swiftImport}`);
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
// 2. Replace bundleURL provider if the original exists and hasn't been replaced
|
|
300
|
-
if (!result.includes(swiftBundleUrl) &&
|
|
301
|
-
swiftOriginalBundleUrlRegex.test(result)) {
|
|
302
|
-
result = result.replace(swiftOriginalBundleUrlRegex, swiftBundleUrl);
|
|
303
|
-
}
|
|
304
|
-
return result;
|
|
305
|
-
}
|
|
306
|
-
/**
|
|
307
|
-
* Public iOS transformer that applies both Objective-C and Swift transforms.
|
|
308
|
-
*/
|
|
309
|
-
function transformIOS(contents) {
|
|
310
|
-
let result = contents;
|
|
311
|
-
result = transformIOSObjC(result);
|
|
312
|
-
result = transformIOSSwift(result);
|
|
313
|
-
return result;
|
|
314
|
-
}
|
|
@@ -1,228 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.getPublicKeyFromConfig = void 0;
|
|
7
|
-
const promises_1 = require("node:fs/promises");
|
|
8
|
-
const path_1 = __importDefault(require("path"));
|
|
9
|
-
const config_plugins_1 = require("expo/config-plugins");
|
|
10
|
-
const package_json_1 = __importDefault(require("../../package.json"));
|
|
11
|
-
const transformers_1 = require("./transformers");
|
|
12
|
-
const loadCliTools = () => import("@hot-updater/cli-tools");
|
|
13
|
-
const loadHotUpdater = () => import("hot-updater");
|
|
14
|
-
const ANDROID_META_DATA_KEYS = {
|
|
15
|
-
channel: "com.hotupdater.CHANNEL",
|
|
16
|
-
fingerprintHash: "com.hotupdater.FINGERPRINT_HASH",
|
|
17
|
-
publicKey: "com.hotupdater.PUBLIC_KEY",
|
|
18
|
-
};
|
|
19
|
-
const removeAndroidMetaData = (application, name) => {
|
|
20
|
-
const metaData = application["meta-data"];
|
|
21
|
-
if (!metaData) {
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
const filtered = (Array.isArray(metaData) ? metaData : [metaData]).filter((item) => item?.$?.["android:name"] !== name);
|
|
25
|
-
if (filtered.length === 0) {
|
|
26
|
-
delete application["meta-data"];
|
|
27
|
-
}
|
|
28
|
-
else {
|
|
29
|
-
application["meta-data"] = filtered;
|
|
30
|
-
}
|
|
31
|
-
};
|
|
32
|
-
const upsertAndroidMetaData = (application, name, value) => {
|
|
33
|
-
removeAndroidMetaData(application, name);
|
|
34
|
-
const metaData = Array.isArray(application["meta-data"])
|
|
35
|
-
? application["meta-data"]
|
|
36
|
-
: application["meta-data"]
|
|
37
|
-
? [application["meta-data"]]
|
|
38
|
-
: [];
|
|
39
|
-
metaData.push({
|
|
40
|
-
$: {
|
|
41
|
-
"android:name": name,
|
|
42
|
-
"android:value": value,
|
|
43
|
-
},
|
|
44
|
-
});
|
|
45
|
-
application["meta-data"] = metaData;
|
|
46
|
-
};
|
|
47
|
-
let fingerprintCache = null;
|
|
48
|
-
const getFingerprint = async () => {
|
|
49
|
-
if (fingerprintCache) {
|
|
50
|
-
return fingerprintCache;
|
|
51
|
-
}
|
|
52
|
-
const { createFingerprintJSON, generateFingerprints } = await loadHotUpdater();
|
|
53
|
-
fingerprintCache = await generateFingerprints();
|
|
54
|
-
await createFingerprintJSON(fingerprintCache);
|
|
55
|
-
return fingerprintCache;
|
|
56
|
-
};
|
|
57
|
-
/**
|
|
58
|
-
* Extract public key for embedding in native configs.
|
|
59
|
-
* Supports multiple sources with priority order:
|
|
60
|
-
* 1. HOT_UPDATER_PRIVATE_KEY environment variable
|
|
61
|
-
* 2. Private key file (extract public key)
|
|
62
|
-
* 3. Public key file (derived from privateKeyPath)
|
|
63
|
-
* 4. Skip with warning (graceful fallback)
|
|
64
|
-
*/
|
|
65
|
-
const getPublicKeyFromConfig = async (signingConfig) => {
|
|
66
|
-
// If signing not enabled, no public key needed
|
|
67
|
-
if (!signingConfig?.enabled) {
|
|
68
|
-
return null;
|
|
69
|
-
}
|
|
70
|
-
const envPrivateKey = process.env.HOT_UPDATER_PRIVATE_KEY;
|
|
71
|
-
if (envPrivateKey) {
|
|
72
|
-
try {
|
|
73
|
-
const { getPublicKeyFromPrivate, loadPrivateKey } = await loadHotUpdater();
|
|
74
|
-
const envPrivateKeyPEM = envPrivateKey.includes("-----BEGIN")
|
|
75
|
-
? envPrivateKey
|
|
76
|
-
: await loadPrivateKey(envPrivateKey);
|
|
77
|
-
const publicKeyPEM = getPublicKeyFromPrivate(envPrivateKeyPEM);
|
|
78
|
-
console.log("[hot-updater] Using public key extracted from HOT_UPDATER_PRIVATE_KEY environment variable");
|
|
79
|
-
return publicKeyPEM.trim();
|
|
80
|
-
}
|
|
81
|
-
catch (error) {
|
|
82
|
-
console.warn("[hot-updater] WARNING: Failed to extract public key from HOT_UPDATER_PRIVATE_KEY:\n" +
|
|
83
|
-
`${error instanceof Error ? error.message : String(error)}\n`);
|
|
84
|
-
// Continue to try other methods
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
// If no privateKeyPath configured, can't proceed with file-based methods
|
|
88
|
-
if (!signingConfig.privateKeyPath) {
|
|
89
|
-
console.warn("[hot-updater] WARNING: signing.enabled is true but no privateKeyPath configured.\n" +
|
|
90
|
-
"Public key will not be embedded. Set HOT_UPDATER_PRIVATE_KEY environment variable or configure privateKeyPath.");
|
|
91
|
-
return null;
|
|
92
|
-
}
|
|
93
|
-
// Resolve paths
|
|
94
|
-
const privateKeyPath = path_1.default.isAbsolute(signingConfig.privateKeyPath)
|
|
95
|
-
? signingConfig.privateKeyPath
|
|
96
|
-
: path_1.default.resolve(process.cwd(), signingConfig.privateKeyPath);
|
|
97
|
-
const publicKeyPath = privateKeyPath.replace(/private-key\.pem$/, "public-key.pem");
|
|
98
|
-
try {
|
|
99
|
-
// Priority 2: Private key file (existing method)
|
|
100
|
-
const { getPublicKeyFromPrivate, loadPrivateKey } = await loadHotUpdater();
|
|
101
|
-
const privateKeyPEM = await loadPrivateKey(privateKeyPath);
|
|
102
|
-
const publicKeyPEM = getPublicKeyFromPrivate(privateKeyPEM);
|
|
103
|
-
console.log(`[hot-updater] Extracted public key from ${privateKeyPath}`);
|
|
104
|
-
return publicKeyPEM.trim();
|
|
105
|
-
}
|
|
106
|
-
catch {
|
|
107
|
-
try {
|
|
108
|
-
// Priority 3: Public key file (fallback)
|
|
109
|
-
const publicKeyPEM = await (0, promises_1.readFile)(publicKeyPath, "utf-8");
|
|
110
|
-
console.log(`[hot-updater] Using public key from ${publicKeyPath}`);
|
|
111
|
-
return publicKeyPEM.trim();
|
|
112
|
-
}
|
|
113
|
-
catch {
|
|
114
|
-
// Priority 4: All sources failed - throw error
|
|
115
|
-
throw new Error("[hot-updater] Failed to load public key for bundle signing.\n\n" +
|
|
116
|
-
"Signing is enabled (signing.enabled: true) but no public key sources found.\n\n" +
|
|
117
|
-
"For EAS builds, use EAS Secrets:\n" +
|
|
118
|
-
' eas env:create --name HOT_UPDATER_PRIVATE_KEY --value "$(cat keys/private-key.pem)"\n\n' +
|
|
119
|
-
"Or add to eas.json:\n" +
|
|
120
|
-
' "env": { "HOT_UPDATER_PRIVATE_KEY": "-----BEGIN PRIVATE KEY-----\\n..." }\n\n' +
|
|
121
|
-
"For local development:\n" +
|
|
122
|
-
" npx hot-updater keys generate\n\n" +
|
|
123
|
-
`Searched locations:\n` +
|
|
124
|
-
` - HOT_UPDATER_PRIVATE_KEY environment variable\n` +
|
|
125
|
-
` - Private key file: ${privateKeyPath}\n` +
|
|
126
|
-
` - Public key file: ${publicKeyPath}\n`);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
};
|
|
130
|
-
exports.getPublicKeyFromConfig = getPublicKeyFromConfig;
|
|
131
|
-
/**
|
|
132
|
-
* Native code modifications - should only run once
|
|
133
|
-
*/
|
|
134
|
-
const withHotUpdaterNativeCode = (config) => {
|
|
135
|
-
let modifiedConfig = config;
|
|
136
|
-
// === iOS: Objective-C & Swift in AppDelegate ===
|
|
137
|
-
modifiedConfig = (0, config_plugins_1.withAppDelegate)(modifiedConfig, (cfg) => {
|
|
138
|
-
let contents = cfg.modResults.contents;
|
|
139
|
-
contents = (0, transformers_1.transformIOS)(contents);
|
|
140
|
-
cfg.modResults.contents = contents;
|
|
141
|
-
return cfg;
|
|
142
|
-
});
|
|
143
|
-
// === Android: Kotlin in MainApplication ===
|
|
144
|
-
modifiedConfig = (0, config_plugins_1.withMainApplication)(modifiedConfig, (cfg) => {
|
|
145
|
-
let contents = cfg.modResults.contents;
|
|
146
|
-
contents = (0, transformers_1.transformAndroid)(contents);
|
|
147
|
-
cfg.modResults.contents = contents;
|
|
148
|
-
return cfg;
|
|
149
|
-
});
|
|
150
|
-
return modifiedConfig;
|
|
151
|
-
};
|
|
152
|
-
/**
|
|
153
|
-
* Configuration updates - should run every time
|
|
154
|
-
*/
|
|
155
|
-
const withHotUpdaterConfigAsync = (props) => (config) => {
|
|
156
|
-
const channel = props.channel || "production";
|
|
157
|
-
let modifiedConfig = config;
|
|
158
|
-
// === iOS: Add channel and fingerprint to Info.plist ===
|
|
159
|
-
modifiedConfig = (0, config_plugins_1.withInfoPlist)(modifiedConfig, async (cfg) => {
|
|
160
|
-
let fingerprintHash = null;
|
|
161
|
-
const { loadConfig } = await loadCliTools();
|
|
162
|
-
const config = await loadConfig(null);
|
|
163
|
-
if (config.updateStrategy !== "appVersion") {
|
|
164
|
-
const fingerprint = await getFingerprint();
|
|
165
|
-
fingerprintHash = fingerprint.ios.hash;
|
|
166
|
-
}
|
|
167
|
-
// Load public key if signing is enabled
|
|
168
|
-
const publicKey = await (0, exports.getPublicKeyFromConfig)(config.signing);
|
|
169
|
-
cfg.modResults.HOT_UPDATER_CHANNEL = channel;
|
|
170
|
-
if (fingerprintHash) {
|
|
171
|
-
cfg.modResults.HOT_UPDATER_FINGERPRINT_HASH = fingerprintHash;
|
|
172
|
-
}
|
|
173
|
-
if (publicKey) {
|
|
174
|
-
cfg.modResults.HOT_UPDATER_PUBLIC_KEY = publicKey;
|
|
175
|
-
}
|
|
176
|
-
return cfg;
|
|
177
|
-
});
|
|
178
|
-
// === Android: Add channel and fingerprint to AndroidManifest.xml ===
|
|
179
|
-
modifiedConfig = (0, config_plugins_1.withAndroidManifest)(modifiedConfig, async (cfg) => {
|
|
180
|
-
let fingerprintHash = null;
|
|
181
|
-
const { loadConfig } = await loadCliTools();
|
|
182
|
-
const config = await loadConfig(null);
|
|
183
|
-
if (config.updateStrategy !== "appVersion") {
|
|
184
|
-
const fingerprint = await getFingerprint();
|
|
185
|
-
fingerprintHash = fingerprint.android.hash;
|
|
186
|
-
}
|
|
187
|
-
// Load public key if signing is enabled
|
|
188
|
-
const publicKey = await (0, exports.getPublicKeyFromConfig)(config.signing);
|
|
189
|
-
const application = cfg.modResults.manifest.application?.[0];
|
|
190
|
-
if (!application) {
|
|
191
|
-
return cfg;
|
|
192
|
-
}
|
|
193
|
-
upsertAndroidMetaData(application, ANDROID_META_DATA_KEYS.channel, channel);
|
|
194
|
-
if (fingerprintHash) {
|
|
195
|
-
upsertAndroidMetaData(application, ANDROID_META_DATA_KEYS.fingerprintHash, fingerprintHash);
|
|
196
|
-
}
|
|
197
|
-
if (publicKey) {
|
|
198
|
-
upsertAndroidMetaData(application, ANDROID_META_DATA_KEYS.publicKey, publicKey);
|
|
199
|
-
}
|
|
200
|
-
return cfg;
|
|
201
|
-
});
|
|
202
|
-
// Remove legacy Hot Updater string resources when prebuild reuses a tree.
|
|
203
|
-
modifiedConfig = (0, config_plugins_1.withStringsXml)(modifiedConfig, (cfg) => {
|
|
204
|
-
const strings = cfg.modResults.resources?.string;
|
|
205
|
-
if (!strings) {
|
|
206
|
-
return cfg;
|
|
207
|
-
}
|
|
208
|
-
cfg.modResults.resources.string = (Array.isArray(strings) ? strings : [strings]).filter((item) => item.$?.name !== "hot_updater_channel" &&
|
|
209
|
-
item.$?.name !== "hot_updater_fingerprint_hash" &&
|
|
210
|
-
item.$?.name !== "hot_updater_public_key");
|
|
211
|
-
return cfg;
|
|
212
|
-
});
|
|
213
|
-
return modifiedConfig;
|
|
214
|
-
};
|
|
215
|
-
/**
|
|
216
|
-
* Main plugin that combines both native code (run once) and config (run always)
|
|
217
|
-
*/
|
|
218
|
-
const withHotUpdater = (config, props = {}) => {
|
|
219
|
-
// Apply plugins in order
|
|
220
|
-
return (0, config_plugins_1.withPlugins)(config, [
|
|
221
|
-
// Native code modifications - wrapped with createRunOncePlugin
|
|
222
|
-
(0, config_plugins_1.createRunOncePlugin)(withHotUpdaterNativeCode, `${package_json_1.default.name}-native`, package_json_1.default.version),
|
|
223
|
-
// Configuration updates - runs every time
|
|
224
|
-
withHotUpdaterConfigAsync(props),
|
|
225
|
-
]);
|
|
226
|
-
};
|
|
227
|
-
// Export the main plugin
|
|
228
|
-
exports.default = withHotUpdater;
|