@hot-updater/react-native 0.29.3 → 0.29.5
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/oldarch/HotUpdaterModule.kt +12 -4
- package/android/src/oldarch/HotUpdaterSpec.kt +3 -5
- package/ios/HotUpdater/Internal/HotUpdater-Bridging-Header.h +0 -1
- package/ios/HotUpdater/Internal/ZipArchiveExtractor.swift +30 -10
- package/lib/commonjs/DefaultResolver.js.map +1 -1
- package/lib/commonjs/checkForUpdate.js.map +1 -1
- package/lib/commonjs/index.js +0 -7
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/native.js.map +1 -1
- package/lib/commonjs/native.spec.js.map +1 -1
- package/lib/commonjs/store.js.map +1 -1
- package/lib/commonjs/types.js.map +1 -1
- package/lib/commonjs/wrap.js.map +1 -1
- package/lib/module/DefaultResolver.js.map +1 -1
- package/lib/module/checkForUpdate.js.map +1 -1
- package/lib/module/index.js +0 -7
- package/lib/module/index.js.map +1 -1
- package/lib/module/native.js.map +1 -1
- package/lib/module/native.spec.js.map +1 -1
- package/lib/module/store.js.map +1 -1
- package/lib/module/types.js.map +1 -1
- package/lib/module/wrap.js.map +1 -1
- package/lib/typescript/commonjs/DefaultResolver.d.ts.map +1 -1
- package/lib/typescript/commonjs/checkForUpdate.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/native.d.ts.map +1 -1
- package/lib/typescript/commonjs/store.d.ts.map +1 -1
- package/lib/typescript/commonjs/types.d.ts.map +1 -1
- package/lib/typescript/commonjs/wrap.d.ts.map +1 -1
- package/lib/typescript/module/DefaultResolver.d.ts.map +1 -1
- package/lib/typescript/module/checkForUpdate.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/native.d.ts.map +1 -1
- package/lib/typescript/module/store.d.ts.map +1 -1
- package/lib/typescript/module/types.d.ts.map +1 -1
- package/lib/typescript/module/wrap.d.ts.map +1 -1
- package/package.json +9 -9
- package/plugin/build/transformers.js +83 -97
- package/plugin/build/withHotUpdater.js +159 -239
- package/src/DefaultResolver.ts +1 -0
- package/src/checkForUpdate.ts +1 -0
- package/src/index.ts +0 -7
- package/src/native.spec.ts +4 -6
- package/src/native.ts +1 -0
- package/src/store.ts +1 -0
- package/src/types.ts +1 -0
- package/src/wrap.tsx +1 -0
|
@@ -1,69 +1,24 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
13
|
-
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
-
function step(op) {
|
|
16
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
18
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
-
switch (op[0]) {
|
|
21
|
-
case 0: case 1: t = op; break;
|
|
22
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
-
default:
|
|
26
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
-
if (t[2]) _.ops.pop();
|
|
31
|
-
_.trys.pop(); continue;
|
|
32
|
-
}
|
|
33
|
-
op = body.call(thisArg, _);
|
|
34
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
39
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
40
4
|
};
|
|
41
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
case 1:
|
|
59
|
-
fingerprintCache = _a.sent();
|
|
60
|
-
return [4 /*yield*/, (0, hot_updater_1.createFingerprintJSON)(fingerprintCache)];
|
|
61
|
-
case 2:
|
|
62
|
-
_a.sent();
|
|
63
|
-
return [2 /*return*/, fingerprintCache];
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
}); };
|
|
6
|
+
const promises_1 = require("node:fs/promises");
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const cli_tools_1 = require("@hot-updater/cli-tools");
|
|
9
|
+
const config_plugins_1 = require("expo/config-plugins");
|
|
10
|
+
const hot_updater_1 = require("hot-updater");
|
|
11
|
+
const package_json_1 = __importDefault(require("../../package.json"));
|
|
12
|
+
const transformers_1 = require("./transformers");
|
|
13
|
+
let fingerprintCache = null;
|
|
14
|
+
const getFingerprint = async () => {
|
|
15
|
+
if (fingerprintCache) {
|
|
16
|
+
return fingerprintCache;
|
|
17
|
+
}
|
|
18
|
+
fingerprintCache = await (0, hot_updater_1.generateFingerprints)();
|
|
19
|
+
await (0, hot_updater_1.createFingerprintJSON)(fingerprintCache);
|
|
20
|
+
return fingerprintCache;
|
|
21
|
+
};
|
|
67
22
|
/**
|
|
68
23
|
* Extract public key for embedding in native configs.
|
|
69
24
|
* Supports multiple sources with priority order:
|
|
@@ -72,92 +27,82 @@ var getFingerprint = function () { return __awaiter(void 0, void 0, void 0, func
|
|
|
72
27
|
* 3. Public key file (derived from privateKeyPath)
|
|
73
28
|
* 4. Skip with warning (graceful fallback)
|
|
74
29
|
*/
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
publicKeyPEM = (0, hot_updater_1.getPublicKeyFromPrivate)(envPrivateKey);
|
|
88
|
-
console.log("[hot-updater] Using public key extracted from HOT_UPDATER_PRIVATE_KEY environment variable");
|
|
89
|
-
return [2 /*return*/, publicKeyPEM.trim()];
|
|
90
|
-
}
|
|
91
|
-
catch (error) {
|
|
92
|
-
console.warn("[hot-updater] WARNING: Failed to extract public key from HOT_UPDATER_PRIVATE_KEY:\n" +
|
|
93
|
-
"".concat(error instanceof Error ? error.message : String(error), "\n"));
|
|
94
|
-
// Continue to try other methods
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
// If no privateKeyPath configured, can't proceed with file-based methods
|
|
98
|
-
if (!signingConfig.privateKeyPath) {
|
|
99
|
-
console.warn("[hot-updater] WARNING: signing.enabled is true but no privateKeyPath configured.\n" +
|
|
100
|
-
"Public key will not be embedded. Set HOT_UPDATER_PRIVATE_KEY environment variable or configure privateKeyPath.");
|
|
101
|
-
return [2 /*return*/, null];
|
|
102
|
-
}
|
|
103
|
-
privateKeyPath = path_1.default.isAbsolute(signingConfig.privateKeyPath)
|
|
104
|
-
? signingConfig.privateKeyPath
|
|
105
|
-
: path_1.default.resolve(process.cwd(), signingConfig.privateKeyPath);
|
|
106
|
-
publicKeyPath = privateKeyPath.replace(/private-key\.pem$/, "public-key.pem");
|
|
107
|
-
_a.label = 1;
|
|
108
|
-
case 1:
|
|
109
|
-
_a.trys.push([1, 3, , 8]);
|
|
110
|
-
return [4 /*yield*/, (0, hot_updater_1.loadPrivateKey)(privateKeyPath)];
|
|
111
|
-
case 2:
|
|
112
|
-
privateKeyPEM = _a.sent();
|
|
113
|
-
publicKeyPEM = (0, hot_updater_1.getPublicKeyFromPrivate)(privateKeyPEM);
|
|
114
|
-
console.log("[hot-updater] Extracted public key from ".concat(privateKeyPath));
|
|
115
|
-
return [2 /*return*/, publicKeyPEM.trim()];
|
|
116
|
-
case 3:
|
|
117
|
-
_privateKeyError_1 = _a.sent();
|
|
118
|
-
_a.label = 4;
|
|
119
|
-
case 4:
|
|
120
|
-
_a.trys.push([4, 6, , 7]);
|
|
121
|
-
return [4 /*yield*/, (0, promises_1.readFile)(publicKeyPath, "utf-8")];
|
|
122
|
-
case 5:
|
|
123
|
-
publicKeyPEM = _a.sent();
|
|
124
|
-
console.log("[hot-updater] Using public key from ".concat(publicKeyPath));
|
|
125
|
-
return [2 /*return*/, publicKeyPEM.trim()];
|
|
126
|
-
case 6:
|
|
127
|
-
_publicKeyError_1 = _a.sent();
|
|
128
|
-
// Priority 4: All sources failed - throw error
|
|
129
|
-
throw new Error("[hot-updater] Failed to load public key for bundle signing.\n\n" +
|
|
130
|
-
"Signing is enabled (signing.enabled: true) but no public key sources found.\n\n" +
|
|
131
|
-
"For EAS builds, use EAS Secrets:\n" +
|
|
132
|
-
' eas env:create --name HOT_UPDATER_PRIVATE_KEY --value "$(cat keys/private-key.pem)"\n\n' +
|
|
133
|
-
"Or add to eas.json:\n" +
|
|
134
|
-
' "env": { "HOT_UPDATER_PRIVATE_KEY": "-----BEGIN PRIVATE KEY-----\\n..." }\n\n' +
|
|
135
|
-
"For local development:\n" +
|
|
136
|
-
" npx hot-updater keys generate\n\n" +
|
|
137
|
-
"Searched locations:\n" +
|
|
138
|
-
" - HOT_UPDATER_PRIVATE_KEY environment variable\n" +
|
|
139
|
-
" - Private key file: ".concat(privateKeyPath, "\n") +
|
|
140
|
-
" - Public key file: ".concat(publicKeyPath, "\n"));
|
|
141
|
-
case 7: return [3 /*break*/, 8];
|
|
142
|
-
case 8: return [2 /*return*/];
|
|
30
|
+
const getPublicKeyFromConfig = async (signingConfig) => {
|
|
31
|
+
// If signing not enabled, no public key needed
|
|
32
|
+
if (!signingConfig?.enabled) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
// Priority 1: Environment variable with private key PEM (EAS builds)
|
|
36
|
+
const envPrivateKey = process.env.HOT_UPDATER_PRIVATE_KEY;
|
|
37
|
+
if (envPrivateKey) {
|
|
38
|
+
try {
|
|
39
|
+
const publicKeyPEM = (0, hot_updater_1.getPublicKeyFromPrivate)(envPrivateKey);
|
|
40
|
+
console.log("[hot-updater] Using public key extracted from HOT_UPDATER_PRIVATE_KEY environment variable");
|
|
41
|
+
return publicKeyPEM.trim();
|
|
143
42
|
}
|
|
144
|
-
|
|
145
|
-
|
|
43
|
+
catch (error) {
|
|
44
|
+
console.warn("[hot-updater] WARNING: Failed to extract public key from HOT_UPDATER_PRIVATE_KEY:\n" +
|
|
45
|
+
`${error instanceof Error ? error.message : String(error)}\n`);
|
|
46
|
+
// Continue to try other methods
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// If no privateKeyPath configured, can't proceed with file-based methods
|
|
50
|
+
if (!signingConfig.privateKeyPath) {
|
|
51
|
+
console.warn("[hot-updater] WARNING: signing.enabled is true but no privateKeyPath configured.\n" +
|
|
52
|
+
"Public key will not be embedded. Set HOT_UPDATER_PRIVATE_KEY environment variable or configure privateKeyPath.");
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
// Resolve paths
|
|
56
|
+
const privateKeyPath = path_1.default.isAbsolute(signingConfig.privateKeyPath)
|
|
57
|
+
? signingConfig.privateKeyPath
|
|
58
|
+
: path_1.default.resolve(process.cwd(), signingConfig.privateKeyPath);
|
|
59
|
+
const publicKeyPath = privateKeyPath.replace(/private-key\.pem$/, "public-key.pem");
|
|
60
|
+
try {
|
|
61
|
+
// Priority 2: Private key file (existing method)
|
|
62
|
+
const privateKeyPEM = await (0, hot_updater_1.loadPrivateKey)(privateKeyPath);
|
|
63
|
+
const publicKeyPEM = (0, hot_updater_1.getPublicKeyFromPrivate)(privateKeyPEM);
|
|
64
|
+
console.log(`[hot-updater] Extracted public key from ${privateKeyPath}`);
|
|
65
|
+
return publicKeyPEM.trim();
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
try {
|
|
69
|
+
// Priority 3: Public key file (fallback)
|
|
70
|
+
const publicKeyPEM = await (0, promises_1.readFile)(publicKeyPath, "utf-8");
|
|
71
|
+
console.log(`[hot-updater] Using public key from ${publicKeyPath}`);
|
|
72
|
+
return publicKeyPEM.trim();
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
// Priority 4: All sources failed - throw error
|
|
76
|
+
throw new Error("[hot-updater] Failed to load public key for bundle signing.\n\n" +
|
|
77
|
+
"Signing is enabled (signing.enabled: true) but no public key sources found.\n\n" +
|
|
78
|
+
"For EAS builds, use EAS Secrets:\n" +
|
|
79
|
+
' eas env:create --name HOT_UPDATER_PRIVATE_KEY --value "$(cat keys/private-key.pem)"\n\n' +
|
|
80
|
+
"Or add to eas.json:\n" +
|
|
81
|
+
' "env": { "HOT_UPDATER_PRIVATE_KEY": "-----BEGIN PRIVATE KEY-----\\n..." }\n\n' +
|
|
82
|
+
"For local development:\n" +
|
|
83
|
+
" npx hot-updater keys generate\n\n" +
|
|
84
|
+
`Searched locations:\n` +
|
|
85
|
+
` - HOT_UPDATER_PRIVATE_KEY environment variable\n` +
|
|
86
|
+
` - Private key file: ${privateKeyPath}\n` +
|
|
87
|
+
` - Public key file: ${publicKeyPath}\n`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
};
|
|
146
91
|
/**
|
|
147
92
|
* Native code modifications - should only run once
|
|
148
93
|
*/
|
|
149
|
-
|
|
150
|
-
|
|
94
|
+
const withHotUpdaterNativeCode = (config) => {
|
|
95
|
+
let modifiedConfig = config;
|
|
151
96
|
// === iOS: Objective-C & Swift in AppDelegate ===
|
|
152
|
-
modifiedConfig = (0, config_plugins_1.withAppDelegate)(modifiedConfig,
|
|
153
|
-
|
|
97
|
+
modifiedConfig = (0, config_plugins_1.withAppDelegate)(modifiedConfig, (cfg) => {
|
|
98
|
+
let contents = cfg.modResults.contents;
|
|
154
99
|
contents = (0, transformers_1.transformIOS)(contents);
|
|
155
100
|
cfg.modResults.contents = contents;
|
|
156
101
|
return cfg;
|
|
157
102
|
});
|
|
158
103
|
// === Android: Kotlin in MainApplication ===
|
|
159
|
-
modifiedConfig = (0, config_plugins_1.withMainApplication)(modifiedConfig,
|
|
160
|
-
|
|
104
|
+
modifiedConfig = (0, config_plugins_1.withMainApplication)(modifiedConfig, (cfg) => {
|
|
105
|
+
let contents = cfg.modResults.contents;
|
|
161
106
|
contents = (0, transformers_1.transformAndroid)(contents);
|
|
162
107
|
cfg.modResults.contents = contents;
|
|
163
108
|
return cfg;
|
|
@@ -167,118 +112,93 @@ var withHotUpdaterNativeCode = function (config) {
|
|
|
167
112
|
/**
|
|
168
113
|
* Configuration updates - should run every time
|
|
169
114
|
*/
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
115
|
+
const withHotUpdaterConfigAsync = (props) => (config) => {
|
|
116
|
+
const channel = props.channel || "production";
|
|
117
|
+
let modifiedConfig = config;
|
|
173
118
|
// === iOS: Add channel and fingerprint to Info.plist ===
|
|
174
|
-
modifiedConfig = (0, config_plugins_1.withInfoPlist)(modifiedConfig,
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
cfg.modResults.HOT_UPDATER_CHANNEL = channel;
|
|
193
|
-
if (fingerprintHash) {
|
|
194
|
-
cfg.modResults.HOT_UPDATER_FINGERPRINT_HASH = fingerprintHash;
|
|
195
|
-
}
|
|
196
|
-
if (publicKey) {
|
|
197
|
-
cfg.modResults.HOT_UPDATER_PUBLIC_KEY = publicKey;
|
|
198
|
-
}
|
|
199
|
-
return [2 /*return*/, cfg];
|
|
200
|
-
}
|
|
201
|
-
});
|
|
202
|
-
}); });
|
|
119
|
+
modifiedConfig = (0, config_plugins_1.withInfoPlist)(modifiedConfig, async (cfg) => {
|
|
120
|
+
let fingerprintHash = null;
|
|
121
|
+
const config = await (0, cli_tools_1.loadConfig)(null);
|
|
122
|
+
if (config.updateStrategy !== "appVersion") {
|
|
123
|
+
const fingerprint = await getFingerprint();
|
|
124
|
+
fingerprintHash = fingerprint.ios.hash;
|
|
125
|
+
}
|
|
126
|
+
// Load public key if signing is enabled
|
|
127
|
+
const publicKey = await getPublicKeyFromConfig(config.signing);
|
|
128
|
+
cfg.modResults.HOT_UPDATER_CHANNEL = channel;
|
|
129
|
+
if (fingerprintHash) {
|
|
130
|
+
cfg.modResults.HOT_UPDATER_FINGERPRINT_HASH = fingerprintHash;
|
|
131
|
+
}
|
|
132
|
+
if (publicKey) {
|
|
133
|
+
cfg.modResults.HOT_UPDATER_PUBLIC_KEY = publicKey;
|
|
134
|
+
}
|
|
135
|
+
return cfg;
|
|
136
|
+
});
|
|
203
137
|
// === Android: Add channel and fingerprint to strings.xml ===
|
|
204
|
-
modifiedConfig = (0, config_plugins_1.withStringsXml)(modifiedConfig,
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
// Remove existing hot_updater_channel entry if it exists
|
|
230
|
-
cfg.modResults.resources.string = cfg.modResults.resources.string.filter(function (item) { return !(item.$ && item.$.name === "hot_updater_channel"); });
|
|
231
|
-
// Add the new hot_updater_channel entry
|
|
232
|
-
cfg.modResults.resources.string.push({
|
|
233
|
-
$: {
|
|
234
|
-
name: "hot_updater_channel",
|
|
235
|
-
moduleConfig: "true",
|
|
236
|
-
},
|
|
237
|
-
_: channel,
|
|
238
|
-
});
|
|
239
|
-
if (fingerprintHash) {
|
|
240
|
-
// Remove existing hot_updater_fingerprint_hash entry if it exists
|
|
241
|
-
cfg.modResults.resources.string =
|
|
242
|
-
cfg.modResults.resources.string.filter(function (item) {
|
|
243
|
-
return !(item.$ && item.$.name === "hot_updater_fingerprint_hash");
|
|
244
|
-
});
|
|
245
|
-
// Add the new hot_updater_fingerprint_hash entry
|
|
246
|
-
cfg.modResults.resources.string.push({
|
|
247
|
-
$: {
|
|
248
|
-
name: "hot_updater_fingerprint_hash",
|
|
249
|
-
moduleConfig: "true",
|
|
250
|
-
},
|
|
251
|
-
_: fingerprintHash,
|
|
252
|
-
});
|
|
253
|
-
}
|
|
254
|
-
if (publicKey) {
|
|
255
|
-
// Remove existing hot_updater_public_key entry if it exists
|
|
256
|
-
cfg.modResults.resources.string =
|
|
257
|
-
cfg.modResults.resources.string.filter(function (item) { return !(item.$ && item.$.name === "hot_updater_public_key"); });
|
|
258
|
-
// Add the new hot_updater_public_key entry
|
|
259
|
-
cfg.modResults.resources.string.push({
|
|
260
|
-
$: {
|
|
261
|
-
name: "hot_updater_public_key",
|
|
262
|
-
moduleConfig: "true",
|
|
263
|
-
},
|
|
264
|
-
_: publicKey,
|
|
265
|
-
});
|
|
266
|
-
}
|
|
267
|
-
return [2 /*return*/, cfg];
|
|
268
|
-
}
|
|
138
|
+
modifiedConfig = (0, config_plugins_1.withStringsXml)(modifiedConfig, async (cfg) => {
|
|
139
|
+
let fingerprintHash = null;
|
|
140
|
+
const config = await (0, cli_tools_1.loadConfig)(null);
|
|
141
|
+
if (config.updateStrategy !== "appVersion") {
|
|
142
|
+
const fingerprint = await getFingerprint();
|
|
143
|
+
fingerprintHash = fingerprint.android.hash;
|
|
144
|
+
}
|
|
145
|
+
// Load public key if signing is enabled
|
|
146
|
+
const publicKey = await getPublicKeyFromConfig(config.signing);
|
|
147
|
+
// Ensure resources object exists
|
|
148
|
+
if (!cfg.modResults.resources) {
|
|
149
|
+
cfg.modResults.resources = {};
|
|
150
|
+
}
|
|
151
|
+
if (!cfg.modResults.resources.string) {
|
|
152
|
+
cfg.modResults.resources.string = [];
|
|
153
|
+
}
|
|
154
|
+
// Remove existing hot_updater_channel entry if it exists
|
|
155
|
+
cfg.modResults.resources.string = cfg.modResults.resources.string.filter((item) => !(item.$ && item.$.name === "hot_updater_channel"));
|
|
156
|
+
// Add the new hot_updater_channel entry
|
|
157
|
+
cfg.modResults.resources.string.push({
|
|
158
|
+
$: {
|
|
159
|
+
name: "hot_updater_channel",
|
|
160
|
+
moduleConfig: "true",
|
|
161
|
+
},
|
|
162
|
+
_: channel,
|
|
269
163
|
});
|
|
270
|
-
|
|
164
|
+
if (fingerprintHash) {
|
|
165
|
+
// Remove existing hot_updater_fingerprint_hash entry if it exists
|
|
166
|
+
cfg.modResults.resources.string =
|
|
167
|
+
cfg.modResults.resources.string.filter((item) => !(item.$ && item.$.name === "hot_updater_fingerprint_hash"));
|
|
168
|
+
// Add the new hot_updater_fingerprint_hash entry
|
|
169
|
+
cfg.modResults.resources.string.push({
|
|
170
|
+
$: {
|
|
171
|
+
name: "hot_updater_fingerprint_hash",
|
|
172
|
+
moduleConfig: "true",
|
|
173
|
+
},
|
|
174
|
+
_: fingerprintHash,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
if (publicKey) {
|
|
178
|
+
// Remove existing hot_updater_public_key entry if it exists
|
|
179
|
+
cfg.modResults.resources.string =
|
|
180
|
+
cfg.modResults.resources.string.filter((item) => !(item.$ && item.$.name === "hot_updater_public_key"));
|
|
181
|
+
// Add the new hot_updater_public_key entry
|
|
182
|
+
cfg.modResults.resources.string.push({
|
|
183
|
+
$: {
|
|
184
|
+
name: "hot_updater_public_key",
|
|
185
|
+
moduleConfig: "true",
|
|
186
|
+
},
|
|
187
|
+
_: publicKey,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
return cfg;
|
|
191
|
+
});
|
|
271
192
|
return modifiedConfig;
|
|
272
|
-
};
|
|
193
|
+
};
|
|
273
194
|
/**
|
|
274
195
|
* Main plugin that combines both native code (run once) and config (run always)
|
|
275
196
|
*/
|
|
276
|
-
|
|
277
|
-
if (props === void 0) { props = {}; }
|
|
197
|
+
const withHotUpdater = (config, props = {}) => {
|
|
278
198
|
// Apply plugins in order
|
|
279
199
|
return (0, config_plugins_1.withPlugins)(config, [
|
|
280
200
|
// Native code modifications - wrapped with createRunOncePlugin
|
|
281
|
-
(0, config_plugins_1.createRunOncePlugin)(withHotUpdaterNativeCode,
|
|
201
|
+
(0, config_plugins_1.createRunOncePlugin)(withHotUpdaterNativeCode, `${package_json_1.default.name}-native`, package_json_1.default.version),
|
|
282
202
|
// Configuration updates - runs every time
|
|
283
203
|
withHotUpdaterConfigAsync(props),
|
|
284
204
|
]);
|
package/src/DefaultResolver.ts
CHANGED
package/src/checkForUpdate.ts
CHANGED
package/src/index.ts
CHANGED
|
@@ -62,13 +62,6 @@ const registerGlobalGetBaseURL = () => {
|
|
|
62
62
|
globalThis.HotUpdaterGetBaseURL = fn;
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
|
-
|
|
66
|
-
// Register to global (React Native, Node.js)
|
|
67
|
-
if (typeof global !== "undefined") {
|
|
68
|
-
if (!global.HotUpdaterGetBaseURL) {
|
|
69
|
-
global.HotUpdaterGetBaseURL = fn;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
65
|
};
|
|
73
66
|
|
|
74
67
|
// Call registration immediately on module load
|
package/src/native.spec.ts
CHANGED
|
@@ -314,9 +314,8 @@ describe("notifyAppReady", () => {
|
|
|
314
314
|
nativeModuleMock.getBaseURL.mockReturnValue("file:///bundle-123");
|
|
315
315
|
nativeModuleMock.updateBundle.mockResolvedValue(true);
|
|
316
316
|
|
|
317
|
-
const { getBaseURL, getBundleId, getManifest, updateBundle } =
|
|
318
|
-
"./native"
|
|
319
|
-
);
|
|
317
|
+
const { getBaseURL, getBundleId, getManifest, updateBundle } =
|
|
318
|
+
await import("./native");
|
|
320
319
|
|
|
321
320
|
expect(getBundleId()).toBe("bundle-123");
|
|
322
321
|
expect(getManifest()).toEqual({
|
|
@@ -366,9 +365,8 @@ describe("notifyAppReady", () => {
|
|
|
366
365
|
nativeModuleMock.getBaseURL.mockReturnValue("file:///bundle-beta");
|
|
367
366
|
nativeModuleMock.resetChannel.mockResolvedValue(true);
|
|
368
367
|
|
|
369
|
-
const { getBaseURL, getBundleId, getManifest, resetChannel } =
|
|
370
|
-
"./native"
|
|
371
|
-
);
|
|
368
|
+
const { getBaseURL, getBundleId, getManifest, resetChannel } =
|
|
369
|
+
await import("./native");
|
|
372
370
|
|
|
373
371
|
expect(getBundleId()).toBe("bundle-beta");
|
|
374
372
|
expect(getManifest()).toEqual({
|
package/src/native.ts
CHANGED
package/src/store.ts
CHANGED
package/src/types.ts
CHANGED