react-native-bspatch 1.1.4 → 2.0.1
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/README.md +22 -32
- package/android/src/main/java/vn/reactnativebspatch/BsPatchModule.kt +15 -102
- package/android/src/main/java/vn/reactnativebspatch/OtaBundleResolver.kt +21 -1
- package/cpp/bsdiff/bspatch.c +1 -0
- package/ios/OtaBundleResolver.swift +16 -1
- package/ios/RNBsPatch.mm +61 -154
- package/lib/commonjs/NativeBsPatch.js.map +1 -1
- package/lib/commonjs/index.js +4 -4
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/ota/OtaProvider.js +26 -22
- package/lib/commonjs/ota/OtaProvider.js.map +1 -1
- package/lib/commonjs/ota/otaAssetResolver.js +8 -2
- package/lib/commonjs/ota/otaAssetResolver.js.map +1 -1
- package/lib/commonjs/ota/otaCore.js +89 -141
- package/lib/commonjs/ota/otaCore.js.map +1 -1
- package/lib/commonjs/ota/otaLogger.js +0 -2
- package/lib/commonjs/ota/otaLogger.js.map +1 -1
- package/lib/commonjs/ota/otaMetadata.js +18 -7
- package/lib/commonjs/ota/otaMetadata.js.map +1 -1
- package/lib/commonjs/ota/storage/GitHubRawStorage.js +3 -1
- package/lib/commonjs/ota/storage/GitHubRawStorage.js.map +1 -1
- package/lib/commonjs/ota/types.js +1 -10
- package/lib/commonjs/ota/types.js.map +1 -1
- package/lib/module/NativeBsPatch.js.map +1 -1
- package/lib/module/index.js +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/ota/OtaProvider.js +26 -22
- package/lib/module/ota/OtaProvider.js.map +1 -1
- package/lib/module/ota/otaAssetResolver.js +8 -2
- package/lib/module/ota/otaAssetResolver.js.map +1 -1
- package/lib/module/ota/otaCore.js +88 -139
- package/lib/module/ota/otaCore.js.map +1 -1
- package/lib/module/ota/otaLogger.js +0 -2
- package/lib/module/ota/otaLogger.js.map +1 -1
- package/lib/module/ota/otaMetadata.js +18 -7
- package/lib/module/ota/otaMetadata.js.map +1 -1
- package/lib/module/ota/storage/GitHubRawStorage.js +3 -1
- package/lib/module/ota/storage/GitHubRawStorage.js.map +1 -1
- package/lib/module/ota/types.js +0 -9
- package/lib/module/ota/types.js.map +1 -1
- package/lib/typescript/NativeBsPatch.d.ts +3 -15
- package/lib/typescript/NativeBsPatch.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +1 -1
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/ota/OtaProvider.d.ts.map +1 -1
- package/lib/typescript/ota/otaAssetResolver.d.ts.map +1 -1
- package/lib/typescript/ota/otaCore.d.ts +5 -42
- package/lib/typescript/ota/otaCore.d.ts.map +1 -1
- package/lib/typescript/ota/otaLogger.d.ts +1 -3
- package/lib/typescript/ota/otaLogger.d.ts.map +1 -1
- package/lib/typescript/ota/otaMetadata.d.ts +2 -2
- package/lib/typescript/ota/otaMetadata.d.ts.map +1 -1
- package/lib/typescript/ota/types.d.ts +18 -54
- package/lib/typescript/ota/types.d.ts.map +1 -1
- package/package.json +3 -6
- package/react-native-bspatch.podspec +0 -1
- package/src/NativeBsPatch.ts +3 -16
- package/src/index.ts +1 -1
- package/src/ota/OtaProvider.tsx +24 -23
- package/src/ota/otaAssetResolver.ts +5 -2
- package/src/ota/otaCore.ts +118 -176
- package/src/ota/otaLogger.ts +0 -2
- package/src/ota/otaMetadata.ts +18 -8
- package/src/ota/storage/GitHubRawStorage.ts +1 -1
- package/src/ota/types.ts +18 -57
- package/tools/build_ota.sh +117 -183
- package/tools/setup_project.js +33 -14
- package/tools/update_registry.js +24 -28
- package/tools/{upload_ota_custom.sh → upload_ota.sh} +33 -114
- package/lib/commonjs/crypto-js.d.js +0 -2
- package/lib/commonjs/crypto-js.d.js.map +0 -1
- package/lib/commonjs/ota/storage/CustomStorage.js +0 -160
- package/lib/commonjs/ota/storage/CustomStorage.js.map +0 -1
- package/lib/commonjs/ota/storage/GitHubReleaseStorage.js +0 -99
- package/lib/commonjs/ota/storage/GitHubReleaseStorage.js.map +0 -1
- package/lib/module/crypto-js.d.js +0 -2
- package/lib/module/crypto-js.d.js.map +0 -1
- package/lib/module/ota/storage/CustomStorage.js +0 -154
- package/lib/module/ota/storage/CustomStorage.js.map +0 -1
- package/lib/module/ota/storage/GitHubReleaseStorage.js +0 -93
- package/lib/module/ota/storage/GitHubReleaseStorage.js.map +0 -1
- package/lib/typescript/ota/storage/CustomStorage.d.ts +0 -12
- package/lib/typescript/ota/storage/CustomStorage.d.ts.map +0 -1
- package/lib/typescript/ota/storage/GitHubReleaseStorage.d.ts +0 -20
- package/lib/typescript/ota/storage/GitHubReleaseStorage.d.ts.map +0 -1
- package/src/crypto-js.d.ts +0 -1
- package/src/ota/storage/CustomStorage.ts +0 -166
- package/src/ota/storage/GitHubReleaseStorage.ts +0 -103
- package/tools/bsdiff +0 -0
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.GitHubReleaseStorageProvider = void 0;
|
|
7
|
-
var _reactNative = require("react-native");
|
|
8
|
-
var _reactNativeBlobUtil = _interopRequireDefault(require("react-native-blob-util"));
|
|
9
|
-
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
|
-
/**
|
|
11
|
-
* GitHub Releases Storage Provider
|
|
12
|
-
*
|
|
13
|
-
* Reads the OTA registry from a GitHub Release asset and resolves download URLs
|
|
14
|
-
* directly from the release. Supports both public and token-authenticated repos.
|
|
15
|
-
*
|
|
16
|
-
* Registry format:
|
|
17
|
-
* - Expected at: `https://raw.githubusercontent.com/{owner}/{repo}/{tag}/{registryPath}`
|
|
18
|
-
* - Asset download: `https://github.com/{owner}/{repo}/releases/download/{tag}/{filename}`
|
|
19
|
-
*/
|
|
20
|
-
|
|
21
|
-
class GitHubReleaseStorageProvider {
|
|
22
|
-
getRawRegistryUrl(config) {
|
|
23
|
-
const {
|
|
24
|
-
repo,
|
|
25
|
-
tag,
|
|
26
|
-
registryPath = 'ota_registry.json'
|
|
27
|
-
} = config.githubRelease;
|
|
28
|
-
return `https://raw.githubusercontent.com/${repo}/${tag}/${registryPath}`;
|
|
29
|
-
}
|
|
30
|
-
getAssetDownloadUrl(config, filename) {
|
|
31
|
-
const {
|
|
32
|
-
repo,
|
|
33
|
-
tag
|
|
34
|
-
} = config.githubRelease;
|
|
35
|
-
return `https://github.com/${repo}/releases/download/${tag}/${filename}`;
|
|
36
|
-
}
|
|
37
|
-
authHeaders(token) {
|
|
38
|
-
if (!token) return {};
|
|
39
|
-
return {
|
|
40
|
-
Authorization: `Bearer ${token}`
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
async fetchManifest(config) {
|
|
44
|
-
if (!config.githubRelease) return config.bundledPatches || [];
|
|
45
|
-
const {
|
|
46
|
-
token
|
|
47
|
-
} = config.githubRelease;
|
|
48
|
-
const url = this.getRawRegistryUrl(config);
|
|
49
|
-
try {
|
|
50
|
-
const res = await _reactNativeBlobUtil.default.fetch('GET', url, this.authHeaders(token));
|
|
51
|
-
if (res.respInfo.status !== 200) {
|
|
52
|
-
throw new Error(`Registry fetch failed with status ${res.respInfo.status}`);
|
|
53
|
-
}
|
|
54
|
-
const registry = typeof res.data === 'string' ? JSON.parse(res.data) : JSON.parse(JSON.stringify(res.data));
|
|
55
|
-
|
|
56
|
-
// Support both flat array (legacy) and structured format
|
|
57
|
-
if (Array.isArray(registry)) {
|
|
58
|
-
return registry.filter(p => !p.platform || p.platform === _reactNative.Platform.OS);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// Structured: apps["1.0.0"].channels["production"].patches[]
|
|
62
|
-
if (!config.appVersion) {
|
|
63
|
-
throw new Error('[GitHubReleaseStorage] config.appVersion is required to query OTA registry');
|
|
64
|
-
}
|
|
65
|
-
const appGroup = registry?.apps?.[config.appVersion];
|
|
66
|
-
const channelGroup = appGroup?.channels?.[config.githubRelease.repo] // use repo as channel fallback
|
|
67
|
-
?? appGroup?.channels?.production ?? appGroup?.flavors?.production;
|
|
68
|
-
if (!channelGroup?.patches?.length) {
|
|
69
|
-
return config.bundledPatches || [];
|
|
70
|
-
}
|
|
71
|
-
return channelGroup.patches.filter(p => !p.platform || p.platform === _reactNative.Platform.OS);
|
|
72
|
-
} catch (error) {
|
|
73
|
-
console.warn('[GitHubStorage] Manifest fetch error:', error.message);
|
|
74
|
-
return config.bundledPatches || [];
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
async getUpdateFileUrl(filename, config) {
|
|
78
|
-
if (!config.githubRelease) throw new Error('githubRelease config missing');
|
|
79
|
-
return this.getAssetDownloadUrl(config, filename);
|
|
80
|
-
}
|
|
81
|
-
async getAssetUrl(hash, ext, config) {
|
|
82
|
-
if (!config.githubRelease) return '';
|
|
83
|
-
const {
|
|
84
|
-
assetBaseUrl,
|
|
85
|
-
tag,
|
|
86
|
-
repo
|
|
87
|
-
} = config.githubRelease;
|
|
88
|
-
|
|
89
|
-
// If a custom CDN/base is provided, use it
|
|
90
|
-
if (assetBaseUrl) {
|
|
91
|
-
return `${assetBaseUrl}/${hash}.${ext}`;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// Fallback: serve from GitHub raw with optional token
|
|
95
|
-
return `https://raw.githubusercontent.com/${repo}/${tag}/assets/${hash}.${ext}`;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
exports.GitHubReleaseStorageProvider = GitHubReleaseStorageProvider;
|
|
99
|
-
//# sourceMappingURL=GitHubReleaseStorage.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["_reactNative","require","_reactNativeBlobUtil","_interopRequireDefault","e","__esModule","default","GitHubReleaseStorageProvider","getRawRegistryUrl","config","repo","tag","registryPath","githubRelease","getAssetDownloadUrl","filename","authHeaders","token","Authorization","fetchManifest","bundledPatches","url","res","ReactNativeBlobUtil","fetch","respInfo","status","Error","registry","data","JSON","parse","stringify","Array","isArray","filter","p","platform","Platform","OS","appVersion","appGroup","apps","channelGroup","channels","production","flavors","patches","length","error","console","warn","message","getUpdateFileUrl","getAssetUrl","hash","ext","assetBaseUrl","exports"],"sourceRoot":"../../../../src","sources":["ota/storage/GitHubReleaseStorage.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":[],"sourceRoot":"../../src","sources":["crypto-js.d.ts"],"mappings":"","ignoreList":[]}
|
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import { Platform } from 'react-native';
|
|
4
|
-
import ReactNativeBlobUtil from 'react-native-blob-util';
|
|
5
|
-
/** Cache tokens per server endpoint so switching configs invalidates stale tokens. */
|
|
6
|
-
const tokenCache = new Map();
|
|
7
|
-
/** Cache registry ETag and parsed patches to avoid redownloading unmodified manifests. */
|
|
8
|
-
const registryCache = new Map();
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Implementation for the custom MinIO-based storage server.
|
|
12
|
-
*/
|
|
13
|
-
export class CustomStorageProvider {
|
|
14
|
-
getEndpoint(config, key, fallback) {
|
|
15
|
-
return config.customServer?.endpoints?.[key] ?? fallback;
|
|
16
|
-
}
|
|
17
|
-
async getAccessToken(config) {
|
|
18
|
-
if (!config.customServer) {
|
|
19
|
-
throw new Error('customServer configuration missing');
|
|
20
|
-
}
|
|
21
|
-
const {
|
|
22
|
-
baseUrl,
|
|
23
|
-
username,
|
|
24
|
-
password
|
|
25
|
-
} = config.customServer;
|
|
26
|
-
const cacheKey = `${baseUrl}|${username}`;
|
|
27
|
-
const now = Date.now();
|
|
28
|
-
const cached = tokenCache.get(cacheKey);
|
|
29
|
-
if (cached && now < cached.expiresAt - 30000) {
|
|
30
|
-
return cached.token;
|
|
31
|
-
}
|
|
32
|
-
const loginPath = this.getEndpoint(config, 'login', 'public/authen/login');
|
|
33
|
-
const loginUrl = baseUrl.endsWith('/') ? `${baseUrl}${loginPath}` : `${baseUrl}/${loginPath}`;
|
|
34
|
-
try {
|
|
35
|
-
const res = await ReactNativeBlobUtil.fetch('POST', loginUrl, {
|
|
36
|
-
'Content-Type': 'application/json; charset=utf-8'
|
|
37
|
-
}, JSON.stringify({
|
|
38
|
-
username,
|
|
39
|
-
password
|
|
40
|
-
}));
|
|
41
|
-
const json = JSON.parse(res.data);
|
|
42
|
-
const token = json.data?.accessTokenInfo?.accessToken;
|
|
43
|
-
if (!token) throw new Error('Login failed: token not found');
|
|
44
|
-
tokenCache.set(cacheKey, {
|
|
45
|
-
token,
|
|
46
|
-
expiresAt: now + 3600000
|
|
47
|
-
}); // 1 hour
|
|
48
|
-
return token;
|
|
49
|
-
} catch (error) {
|
|
50
|
-
throw new Error(`Authentication failed: ${error.message}`);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
async fetchManifest(config) {
|
|
54
|
-
if (!config.customServer) return config.bundledPatches || [];
|
|
55
|
-
const {
|
|
56
|
-
baseUrl,
|
|
57
|
-
channel,
|
|
58
|
-
baseFolder = 'bspatch'
|
|
59
|
-
} = config.customServer;
|
|
60
|
-
const registryPath = `${baseFolder}/ota_registry.json`;
|
|
61
|
-
const regCacheKey = `${baseUrl}|${registryPath}|${config.appVersion}|${channel}`;
|
|
62
|
-
const cachedReg = registryCache.get(regCacheKey);
|
|
63
|
-
try {
|
|
64
|
-
const token = await this.getAccessToken(config);
|
|
65
|
-
const normalizedBaseUrl = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;
|
|
66
|
-
const genLinkPath = this.getEndpoint(config, 'genDownloadLink', 'api/minio/gen-download-link');
|
|
67
|
-
const genLinkUrl = `${normalizedBaseUrl}/${genLinkPath}?pathFile=${encodeURIComponent(registryPath)}`;
|
|
68
|
-
const linkRes = await ReactNativeBlobUtil.fetch('GET', genLinkUrl, {
|
|
69
|
-
Authorization: `Bearer ${token}`
|
|
70
|
-
});
|
|
71
|
-
const linkJson = JSON.parse(linkRes.data);
|
|
72
|
-
const registryUrl = linkJson.data;
|
|
73
|
-
if (!registryUrl) throw new Error('Failed to generate registry download link');
|
|
74
|
-
const reqHeaders = {};
|
|
75
|
-
if (cachedReg?.etag) {
|
|
76
|
-
reqHeaders['If-None-Match'] = cachedReg.etag;
|
|
77
|
-
}
|
|
78
|
-
const registryRes = await ReactNativeBlobUtil.fetch('GET', registryUrl, reqHeaders);
|
|
79
|
-
if (registryRes.respInfo.status === 304 && cachedReg) {
|
|
80
|
-
return cachedReg.patches;
|
|
81
|
-
}
|
|
82
|
-
if (registryRes.respInfo.status !== 200) {
|
|
83
|
-
throw new Error(`Registry fetch failed with status ${registryRes.respInfo.status}`);
|
|
84
|
-
}
|
|
85
|
-
const etag = registryRes.respInfo.headers?.['etag'] || registryRes.respInfo.headers?.['ETag'];
|
|
86
|
-
if (!config.appVersion) {
|
|
87
|
-
throw new Error('[CustomStorage] config.appVersion is required to query OTA registry');
|
|
88
|
-
}
|
|
89
|
-
const registry = JSON.parse(registryRes.data);
|
|
90
|
-
const appGroup = registry?.apps?.[config.appVersion];
|
|
91
|
-
const flavorGroup = appGroup?.flavors?.[channel.toLowerCase()];
|
|
92
|
-
if (!flavorGroup || !flavorGroup.patches?.length) {
|
|
93
|
-
return config.bundledPatches || [];
|
|
94
|
-
}
|
|
95
|
-
const matchedPatches = (flavorGroup.patches || []).filter(p => p.platform === Platform.OS);
|
|
96
|
-
registryCache.set(regCacheKey, {
|
|
97
|
-
etag,
|
|
98
|
-
patches: matchedPatches
|
|
99
|
-
});
|
|
100
|
-
return matchedPatches;
|
|
101
|
-
} catch (error) {
|
|
102
|
-
console.warn('[CustomStorage] Manifest fetch error:', error.message);
|
|
103
|
-
return cachedReg?.patches || config.bundledPatches || [];
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
async getUpdateFileUrl(filename, config) {
|
|
107
|
-
if (!config.customServer) throw new Error('customServer config missing');
|
|
108
|
-
const {
|
|
109
|
-
baseUrl,
|
|
110
|
-
baseFolder = 'bspatch',
|
|
111
|
-
useMinio
|
|
112
|
-
} = config.customServer;
|
|
113
|
-
const normalizedBaseUrl = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;
|
|
114
|
-
const channel = config.customServer.channel.toLowerCase();
|
|
115
|
-
const remotePath = `${baseFolder}/${config.appVersion}/${channel}/${filename}`;
|
|
116
|
-
if (useMinio) {
|
|
117
|
-
const token = await this.getAccessToken(config);
|
|
118
|
-
const genLinkPath = this.getEndpoint(config, 'genDownloadLink', 'api/minio/gen-download-link');
|
|
119
|
-
const genLinkUrl = `${normalizedBaseUrl}/${genLinkPath}?pathFile=${encodeURIComponent(remotePath)}`;
|
|
120
|
-
const res = await ReactNativeBlobUtil.fetch('GET', genLinkUrl, {
|
|
121
|
-
Authorization: `Bearer ${token}`
|
|
122
|
-
});
|
|
123
|
-
const json = JSON.parse(res.data);
|
|
124
|
-
if (!json.data) throw new Error(`Failed to generate link for: ${filename}`);
|
|
125
|
-
return json.data;
|
|
126
|
-
}
|
|
127
|
-
const downloadPath = this.getEndpoint(config, 'downloadFile', 'files/downloadStreamFile');
|
|
128
|
-
return `${normalizedBaseUrl}/${downloadPath}?filepath=${encodeURIComponent(remotePath)}`;
|
|
129
|
-
}
|
|
130
|
-
async getAssetUrl(hash, ext, config) {
|
|
131
|
-
if (!config.customServer) return '';
|
|
132
|
-
const {
|
|
133
|
-
baseUrl,
|
|
134
|
-
baseFolder = 'bspatch',
|
|
135
|
-
useMinio
|
|
136
|
-
} = config.customServer;
|
|
137
|
-
const normalizedBaseUrl = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;
|
|
138
|
-
const filename = `${hash}.${ext}`;
|
|
139
|
-
const remotePath = `${baseFolder}/assets/${filename}`;
|
|
140
|
-
if (useMinio) {
|
|
141
|
-
const token = await this.getAccessToken(config);
|
|
142
|
-
const genLinkPath = this.getEndpoint(config, 'genDownloadLink', 'api/minio/gen-download-link');
|
|
143
|
-
const genLinkUrl = `${normalizedBaseUrl}/${genLinkPath}?pathFile=${encodeURIComponent(remotePath)}`;
|
|
144
|
-
const res = await ReactNativeBlobUtil.fetch('GET', genLinkUrl, {
|
|
145
|
-
Authorization: `Bearer ${token}`
|
|
146
|
-
});
|
|
147
|
-
const json = JSON.parse(res.data);
|
|
148
|
-
return json.data || '';
|
|
149
|
-
}
|
|
150
|
-
const downloadPath = this.getEndpoint(config, 'downloadFile', 'files/downloadStreamFile');
|
|
151
|
-
return `${normalizedBaseUrl}/${downloadPath}?filepath=${encodeURIComponent(remotePath)}`;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
//# sourceMappingURL=CustomStorage.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["Platform","ReactNativeBlobUtil","tokenCache","Map","registryCache","CustomStorageProvider","getEndpoint","config","key","fallback","customServer","endpoints","getAccessToken","Error","baseUrl","username","password","cacheKey","now","Date","cached","get","expiresAt","token","loginPath","loginUrl","endsWith","res","fetch","JSON","stringify","json","parse","data","accessTokenInfo","accessToken","set","error","message","fetchManifest","bundledPatches","channel","baseFolder","registryPath","regCacheKey","appVersion","cachedReg","normalizedBaseUrl","slice","genLinkPath","genLinkUrl","encodeURIComponent","linkRes","Authorization","linkJson","registryUrl","reqHeaders","etag","registryRes","respInfo","status","patches","headers","registry","appGroup","apps","flavorGroup","flavors","toLowerCase","length","matchedPatches","filter","p","platform","OS","console","warn","getUpdateFileUrl","filename","useMinio","remotePath","downloadPath","getAssetUrl","hash","ext"],"sourceRoot":"../../../../src","sources":["ota/storage/CustomStorage.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* GitHub Releases Storage Provider
|
|
5
|
-
*
|
|
6
|
-
* Reads the OTA registry from a GitHub Release asset and resolves download URLs
|
|
7
|
-
* directly from the release. Supports both public and token-authenticated repos.
|
|
8
|
-
*
|
|
9
|
-
* Registry format:
|
|
10
|
-
* - Expected at: `https://raw.githubusercontent.com/{owner}/{repo}/{tag}/{registryPath}`
|
|
11
|
-
* - Asset download: `https://github.com/{owner}/{repo}/releases/download/{tag}/{filename}`
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
import { Platform } from 'react-native';
|
|
15
|
-
import ReactNativeBlobUtil from 'react-native-blob-util';
|
|
16
|
-
export class GitHubReleaseStorageProvider {
|
|
17
|
-
getRawRegistryUrl(config) {
|
|
18
|
-
const {
|
|
19
|
-
repo,
|
|
20
|
-
tag,
|
|
21
|
-
registryPath = 'ota_registry.json'
|
|
22
|
-
} = config.githubRelease;
|
|
23
|
-
return `https://raw.githubusercontent.com/${repo}/${tag}/${registryPath}`;
|
|
24
|
-
}
|
|
25
|
-
getAssetDownloadUrl(config, filename) {
|
|
26
|
-
const {
|
|
27
|
-
repo,
|
|
28
|
-
tag
|
|
29
|
-
} = config.githubRelease;
|
|
30
|
-
return `https://github.com/${repo}/releases/download/${tag}/${filename}`;
|
|
31
|
-
}
|
|
32
|
-
authHeaders(token) {
|
|
33
|
-
if (!token) return {};
|
|
34
|
-
return {
|
|
35
|
-
Authorization: `Bearer ${token}`
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
async fetchManifest(config) {
|
|
39
|
-
if (!config.githubRelease) return config.bundledPatches || [];
|
|
40
|
-
const {
|
|
41
|
-
token
|
|
42
|
-
} = config.githubRelease;
|
|
43
|
-
const url = this.getRawRegistryUrl(config);
|
|
44
|
-
try {
|
|
45
|
-
const res = await ReactNativeBlobUtil.fetch('GET', url, this.authHeaders(token));
|
|
46
|
-
if (res.respInfo.status !== 200) {
|
|
47
|
-
throw new Error(`Registry fetch failed with status ${res.respInfo.status}`);
|
|
48
|
-
}
|
|
49
|
-
const registry = typeof res.data === 'string' ? JSON.parse(res.data) : JSON.parse(JSON.stringify(res.data));
|
|
50
|
-
|
|
51
|
-
// Support both flat array (legacy) and structured format
|
|
52
|
-
if (Array.isArray(registry)) {
|
|
53
|
-
return registry.filter(p => !p.platform || p.platform === Platform.OS);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// Structured: apps["1.0.0"].channels["production"].patches[]
|
|
57
|
-
if (!config.appVersion) {
|
|
58
|
-
throw new Error('[GitHubReleaseStorage] config.appVersion is required to query OTA registry');
|
|
59
|
-
}
|
|
60
|
-
const appGroup = registry?.apps?.[config.appVersion];
|
|
61
|
-
const channelGroup = appGroup?.channels?.[config.githubRelease.repo] // use repo as channel fallback
|
|
62
|
-
?? appGroup?.channels?.production ?? appGroup?.flavors?.production;
|
|
63
|
-
if (!channelGroup?.patches?.length) {
|
|
64
|
-
return config.bundledPatches || [];
|
|
65
|
-
}
|
|
66
|
-
return channelGroup.patches.filter(p => !p.platform || p.platform === Platform.OS);
|
|
67
|
-
} catch (error) {
|
|
68
|
-
console.warn('[GitHubStorage] Manifest fetch error:', error.message);
|
|
69
|
-
return config.bundledPatches || [];
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
async getUpdateFileUrl(filename, config) {
|
|
73
|
-
if (!config.githubRelease) throw new Error('githubRelease config missing');
|
|
74
|
-
return this.getAssetDownloadUrl(config, filename);
|
|
75
|
-
}
|
|
76
|
-
async getAssetUrl(hash, ext, config) {
|
|
77
|
-
if (!config.githubRelease) return '';
|
|
78
|
-
const {
|
|
79
|
-
assetBaseUrl,
|
|
80
|
-
tag,
|
|
81
|
-
repo
|
|
82
|
-
} = config.githubRelease;
|
|
83
|
-
|
|
84
|
-
// If a custom CDN/base is provided, use it
|
|
85
|
-
if (assetBaseUrl) {
|
|
86
|
-
return `${assetBaseUrl}/${hash}.${ext}`;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Fallback: serve from GitHub raw with optional token
|
|
90
|
-
return `https://raw.githubusercontent.com/${repo}/${tag}/assets/${hash}.${ext}`;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
//# sourceMappingURL=GitHubReleaseStorage.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["Platform","ReactNativeBlobUtil","GitHubReleaseStorageProvider","getRawRegistryUrl","config","repo","tag","registryPath","githubRelease","getAssetDownloadUrl","filename","authHeaders","token","Authorization","fetchManifest","bundledPatches","url","res","fetch","respInfo","status","Error","registry","data","JSON","parse","stringify","Array","isArray","filter","p","platform","OS","appVersion","appGroup","apps","channelGroup","channels","production","flavors","patches","length","error","console","warn","message","getUpdateFileUrl","getAssetUrl","hash","ext","assetBaseUrl"],"sourceRoot":"../../../../src","sources":["ota/storage/GitHubReleaseStorage.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { OtaPatch, OtaConfig, OtaStorageProvider } from '../types';
|
|
2
|
-
/**
|
|
3
|
-
* Implementation for the custom MinIO-based storage server.
|
|
4
|
-
*/
|
|
5
|
-
export declare class CustomStorageProvider implements OtaStorageProvider {
|
|
6
|
-
private getEndpoint;
|
|
7
|
-
private getAccessToken;
|
|
8
|
-
fetchManifest(config: OtaConfig): Promise<OtaPatch[]>;
|
|
9
|
-
getUpdateFileUrl(filename: string, config: OtaConfig): Promise<string>;
|
|
10
|
-
getAssetUrl(hash: string, ext: string, config: OtaConfig): Promise<string>;
|
|
11
|
-
}
|
|
12
|
-
//# sourceMappingURL=CustomStorage.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"CustomStorage.d.ts","sourceRoot":"","sources":["../../../../src/ota/storage/CustomStorage.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAiBxE;;GAEG;AACH,qBAAa,qBAAsB,YAAW,kBAAkB;IAC9D,OAAO,CAAC,WAAW;YAIL,cAAc;IAqCtB,aAAa,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAuDrD,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC;IAwBtE,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC;CAsBjF"}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* GitHub Releases Storage Provider
|
|
3
|
-
*
|
|
4
|
-
* Reads the OTA registry from a GitHub Release asset and resolves download URLs
|
|
5
|
-
* directly from the release. Supports both public and token-authenticated repos.
|
|
6
|
-
*
|
|
7
|
-
* Registry format:
|
|
8
|
-
* - Expected at: `https://raw.githubusercontent.com/{owner}/{repo}/{tag}/{registryPath}`
|
|
9
|
-
* - Asset download: `https://github.com/{owner}/{repo}/releases/download/{tag}/{filename}`
|
|
10
|
-
*/
|
|
11
|
-
import type { OtaPatch, OtaConfig, OtaStorageProvider } from '../types';
|
|
12
|
-
export declare class GitHubReleaseStorageProvider implements OtaStorageProvider {
|
|
13
|
-
private getRawRegistryUrl;
|
|
14
|
-
private getAssetDownloadUrl;
|
|
15
|
-
private authHeaders;
|
|
16
|
-
fetchManifest(config: OtaConfig): Promise<OtaPatch[]>;
|
|
17
|
-
getUpdateFileUrl(filename: string, config: OtaConfig): Promise<string>;
|
|
18
|
-
getAssetUrl(hash: string, ext: string, config: OtaConfig): Promise<string>;
|
|
19
|
-
}
|
|
20
|
-
//# sourceMappingURL=GitHubReleaseStorage.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"GitHubReleaseStorage.d.ts","sourceRoot":"","sources":["../../../../src/ota/storage/GitHubReleaseStorage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAExE,qBAAa,4BAA6B,YAAW,kBAAkB;IACnE,OAAO,CAAC,iBAAiB;IAKzB,OAAO,CAAC,mBAAmB;IAK3B,OAAO,CAAC,WAAW;IAKb,aAAa,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAqDrD,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC;IAKtE,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC;CAanF"}
|
package/src/crypto-js.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
declare module 'crypto-js';
|
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
import { Platform } from 'react-native';
|
|
2
|
-
import ReactNativeBlobUtil from 'react-native-blob-util';
|
|
3
|
-
import type { OtaPatch, OtaConfig, OtaStorageProvider } from '../types';
|
|
4
|
-
|
|
5
|
-
interface TokenCache {
|
|
6
|
-
token: string;
|
|
7
|
-
expiresAt: number;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
interface RegistryCache {
|
|
11
|
-
etag?: string;
|
|
12
|
-
patches: OtaPatch[];
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/** Cache tokens per server endpoint so switching configs invalidates stale tokens. */
|
|
16
|
-
const tokenCache = new Map<string, TokenCache>();
|
|
17
|
-
/** Cache registry ETag and parsed patches to avoid redownloading unmodified manifests. */
|
|
18
|
-
const registryCache = new Map<string, RegistryCache>();
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Implementation for the custom MinIO-based storage server.
|
|
22
|
-
*/
|
|
23
|
-
export class CustomStorageProvider implements OtaStorageProvider {
|
|
24
|
-
private getEndpoint(config: OtaConfig, key: 'login' | 'genDownloadLink' | 'downloadFile', fallback: string): string {
|
|
25
|
-
return config.customServer?.endpoints?.[key] ?? fallback;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
private async getAccessToken(config: OtaConfig): Promise<string> {
|
|
29
|
-
if (!config.customServer) {
|
|
30
|
-
throw new Error('customServer configuration missing');
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const { baseUrl, username, password } = config.customServer;
|
|
34
|
-
const cacheKey = `${baseUrl}|${username}`;
|
|
35
|
-
const now = Date.now();
|
|
36
|
-
|
|
37
|
-
const cached = tokenCache.get(cacheKey);
|
|
38
|
-
if (cached && now < cached.expiresAt - 30000) {
|
|
39
|
-
return cached.token;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const loginPath = this.getEndpoint(config, 'login', 'public/authen/login');
|
|
43
|
-
const loginUrl = baseUrl.endsWith('/') ? `${baseUrl}${loginPath}` : `${baseUrl}/${loginPath}`;
|
|
44
|
-
|
|
45
|
-
try {
|
|
46
|
-
const res = await ReactNativeBlobUtil.fetch(
|
|
47
|
-
'POST',
|
|
48
|
-
loginUrl,
|
|
49
|
-
{ 'Content-Type': 'application/json; charset=utf-8' },
|
|
50
|
-
JSON.stringify({ username, password })
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
const json = JSON.parse(res.data);
|
|
54
|
-
const token = json.data?.accessTokenInfo?.accessToken;
|
|
55
|
-
|
|
56
|
-
if (!token) throw new Error('Login failed: token not found');
|
|
57
|
-
|
|
58
|
-
tokenCache.set(cacheKey, { token, expiresAt: now + 3600000 }); // 1 hour
|
|
59
|
-
return token;
|
|
60
|
-
} catch (error) {
|
|
61
|
-
throw new Error(`Authentication failed: ${(error as Error).message}`);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
async fetchManifest(config: OtaConfig): Promise<OtaPatch[]> {
|
|
66
|
-
if (!config.customServer) return config.bundledPatches || [];
|
|
67
|
-
|
|
68
|
-
const { baseUrl, channel, baseFolder = 'bspatch' } = config.customServer;
|
|
69
|
-
const registryPath = `${baseFolder}/ota_registry.json`;
|
|
70
|
-
const regCacheKey = `${baseUrl}|${registryPath}|${config.appVersion}|${channel}`;
|
|
71
|
-
const cachedReg = registryCache.get(regCacheKey);
|
|
72
|
-
|
|
73
|
-
try {
|
|
74
|
-
const token = await this.getAccessToken(config);
|
|
75
|
-
const normalizedBaseUrl = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;
|
|
76
|
-
const genLinkPath = this.getEndpoint(config, 'genDownloadLink', 'api/minio/gen-download-link');
|
|
77
|
-
const genLinkUrl = `${normalizedBaseUrl}/${genLinkPath}?pathFile=${encodeURIComponent(registryPath)}`;
|
|
78
|
-
|
|
79
|
-
const linkRes = await ReactNativeBlobUtil.fetch('GET', genLinkUrl, {
|
|
80
|
-
Authorization: `Bearer ${token}`,
|
|
81
|
-
});
|
|
82
|
-
const linkJson = JSON.parse(linkRes.data);
|
|
83
|
-
const registryUrl = linkJson.data;
|
|
84
|
-
if (!registryUrl) throw new Error('Failed to generate registry download link');
|
|
85
|
-
|
|
86
|
-
const reqHeaders: Record<string, string> = {};
|
|
87
|
-
if (cachedReg?.etag) {
|
|
88
|
-
reqHeaders['If-None-Match'] = cachedReg.etag;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const registryRes = await ReactNativeBlobUtil.fetch('GET', registryUrl, reqHeaders);
|
|
92
|
-
if (registryRes.respInfo.status === 304 && cachedReg) {
|
|
93
|
-
return cachedReg.patches;
|
|
94
|
-
}
|
|
95
|
-
if (registryRes.respInfo.status !== 200) {
|
|
96
|
-
throw new Error(`Registry fetch failed with status ${registryRes.respInfo.status}`);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const etag = registryRes.respInfo.headers?.['etag'] || registryRes.respInfo.headers?.['ETag'];
|
|
100
|
-
if (!config.appVersion) {
|
|
101
|
-
throw new Error('[CustomStorage] config.appVersion is required to query OTA registry');
|
|
102
|
-
}
|
|
103
|
-
const registry = JSON.parse(registryRes.data);
|
|
104
|
-
const appGroup = registry?.apps?.[config.appVersion];
|
|
105
|
-
const flavorGroup = appGroup?.flavors?.[channel.toLowerCase()];
|
|
106
|
-
|
|
107
|
-
if (!flavorGroup || !flavorGroup.patches?.length) {
|
|
108
|
-
return config.bundledPatches || [];
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
const matchedPatches = (flavorGroup.patches || []).filter((p: OtaPatch) => p.platform === Platform.OS);
|
|
112
|
-
registryCache.set(regCacheKey, { etag, patches: matchedPatches });
|
|
113
|
-
return matchedPatches;
|
|
114
|
-
} catch (error) {
|
|
115
|
-
console.warn('[CustomStorage] Manifest fetch error:', (error as Error).message);
|
|
116
|
-
return cachedReg?.patches || config.bundledPatches || [];
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
async getUpdateFileUrl(filename: string, config: OtaConfig): Promise<string> {
|
|
121
|
-
if (!config.customServer) throw new Error('customServer config missing');
|
|
122
|
-
|
|
123
|
-
const { baseUrl, baseFolder = 'bspatch', useMinio } = config.customServer;
|
|
124
|
-
const normalizedBaseUrl = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;
|
|
125
|
-
const channel = config.customServer.channel.toLowerCase();
|
|
126
|
-
const remotePath = `${baseFolder}/${config.appVersion}/${channel}/${filename}`;
|
|
127
|
-
|
|
128
|
-
if (useMinio) {
|
|
129
|
-
const token = await this.getAccessToken(config);
|
|
130
|
-
const genLinkPath = this.getEndpoint(config, 'genDownloadLink', 'api/minio/gen-download-link');
|
|
131
|
-
const genLinkUrl = `${normalizedBaseUrl}/${genLinkPath}?pathFile=${encodeURIComponent(remotePath)}`;
|
|
132
|
-
const res = await ReactNativeBlobUtil.fetch('GET', genLinkUrl, {
|
|
133
|
-
Authorization: `Bearer ${token}`,
|
|
134
|
-
});
|
|
135
|
-
const json = JSON.parse(res.data);
|
|
136
|
-
if (!json.data) throw new Error(`Failed to generate link for: ${filename}`);
|
|
137
|
-
return json.data;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
const downloadPath = this.getEndpoint(config, 'downloadFile', 'files/downloadStreamFile');
|
|
141
|
-
return `${normalizedBaseUrl}/${downloadPath}?filepath=${encodeURIComponent(remotePath)}`;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
async getAssetUrl(hash: string, ext: string, config: OtaConfig): Promise<string> {
|
|
145
|
-
if (!config.customServer) return '';
|
|
146
|
-
|
|
147
|
-
const { baseUrl, baseFolder = 'bspatch', useMinio } = config.customServer;
|
|
148
|
-
const normalizedBaseUrl = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;
|
|
149
|
-
const filename = `${hash}.${ext}`;
|
|
150
|
-
const remotePath = `${baseFolder}/assets/${filename}`;
|
|
151
|
-
|
|
152
|
-
if (useMinio) {
|
|
153
|
-
const token = await this.getAccessToken(config);
|
|
154
|
-
const genLinkPath = this.getEndpoint(config, 'genDownloadLink', 'api/minio/gen-download-link');
|
|
155
|
-
const genLinkUrl = `${normalizedBaseUrl}/${genLinkPath}?pathFile=${encodeURIComponent(remotePath)}`;
|
|
156
|
-
const res = await ReactNativeBlobUtil.fetch('GET', genLinkUrl, {
|
|
157
|
-
Authorization: `Bearer ${token}`,
|
|
158
|
-
});
|
|
159
|
-
const json = JSON.parse(res.data);
|
|
160
|
-
return json.data || '';
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
const downloadPath = this.getEndpoint(config, 'downloadFile', 'files/downloadStreamFile');
|
|
164
|
-
return `${normalizedBaseUrl}/${downloadPath}?filepath=${encodeURIComponent(remotePath)}`;
|
|
165
|
-
}
|
|
166
|
-
}
|