@vanikya/ota-react-native 0.1.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/README.md +223 -0
- package/android/build.gradle +58 -0
- package/android/src/main/AndroidManifest.xml +4 -0
- package/android/src/main/java/com/otaupdate/OTAUpdateModule.kt +185 -0
- package/android/src/main/java/com/otaupdate/OTAUpdatePackage.kt +16 -0
- package/ios/OTAUpdate.m +61 -0
- package/ios/OTAUpdate.swift +194 -0
- package/lib/commonjs/OTAProvider.js +113 -0
- package/lib/commonjs/OTAProvider.js.map +1 -0
- package/lib/commonjs/hooks/useOTAUpdate.js +272 -0
- package/lib/commonjs/hooks/useOTAUpdate.js.map +1 -0
- package/lib/commonjs/index.js +98 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/utils/api.js +60 -0
- package/lib/commonjs/utils/api.js.map +1 -0
- package/lib/commonjs/utils/storage.js +209 -0
- package/lib/commonjs/utils/storage.js.map +1 -0
- package/lib/commonjs/utils/verification.js +145 -0
- package/lib/commonjs/utils/verification.js.map +1 -0
- package/lib/module/OTAProvider.js +104 -0
- package/lib/module/OTAProvider.js.map +1 -0
- package/lib/module/hooks/useOTAUpdate.js +266 -0
- package/lib/module/hooks/useOTAUpdate.js.map +1 -0
- package/lib/module/index.js +11 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/utils/api.js +52 -0
- package/lib/module/utils/api.js.map +1 -0
- package/lib/module/utils/storage.js +202 -0
- package/lib/module/utils/storage.js.map +1 -0
- package/lib/module/utils/verification.js +137 -0
- package/lib/module/utils/verification.js.map +1 -0
- package/lib/typescript/OTAProvider.d.ts +28 -0
- package/lib/typescript/OTAProvider.d.ts.map +1 -0
- package/lib/typescript/hooks/useOTAUpdate.d.ts +35 -0
- package/lib/typescript/hooks/useOTAUpdate.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +12 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/utils/api.d.ts +47 -0
- package/lib/typescript/utils/api.d.ts.map +1 -0
- package/lib/typescript/utils/storage.d.ts +32 -0
- package/lib/typescript/utils/storage.d.ts.map +1 -0
- package/lib/typescript/utils/verification.d.ts +11 -0
- package/lib/typescript/utils/verification.d.ts.map +1 -0
- package/ota-update.podspec +21 -0
- package/package.json +83 -0
- package/src/OTAProvider.tsx +160 -0
- package/src/hooks/useOTAUpdate.ts +344 -0
- package/src/index.ts +36 -0
- package/src/utils/api.ts +99 -0
- package/src/utils/storage.ts +249 -0
- package/src/utils/verification.ts +167 -0
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import CommonCrypto
|
|
3
|
+
|
|
4
|
+
@objc(OTAUpdate)
|
|
5
|
+
class OTAUpdate: NSObject {
|
|
6
|
+
|
|
7
|
+
// MARK: - File System Operations
|
|
8
|
+
|
|
9
|
+
@objc
|
|
10
|
+
func getDocumentDirectory() -> String {
|
|
11
|
+
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
|
|
12
|
+
return paths[0].path + "/"
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@objc
|
|
16
|
+
func writeFile(_ path: String, content: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
17
|
+
do {
|
|
18
|
+
try content.write(toFile: path, atomically: true, encoding: .utf8)
|
|
19
|
+
resolver(nil)
|
|
20
|
+
} catch {
|
|
21
|
+
rejecter("WRITE_ERROR", "Failed to write file: \(error.localizedDescription)", error)
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
@objc
|
|
26
|
+
func writeFileBase64(_ path: String, base64Content: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
27
|
+
guard let data = Data(base64Encoded: base64Content) else {
|
|
28
|
+
rejecter("DECODE_ERROR", "Invalid base64 content", nil)
|
|
29
|
+
return
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
do {
|
|
33
|
+
try data.write(to: URL(fileURLWithPath: path))
|
|
34
|
+
resolver(nil)
|
|
35
|
+
} catch {
|
|
36
|
+
rejecter("WRITE_ERROR", "Failed to write file: \(error.localizedDescription)", error)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@objc
|
|
41
|
+
func readFile(_ path: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
42
|
+
do {
|
|
43
|
+
let content = try String(contentsOfFile: path, encoding: .utf8)
|
|
44
|
+
resolver(content)
|
|
45
|
+
} catch {
|
|
46
|
+
rejecter("READ_ERROR", "Failed to read file: \(error.localizedDescription)", error)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@objc
|
|
51
|
+
func readFileBase64(_ path: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
52
|
+
do {
|
|
53
|
+
let data = try Data(contentsOf: URL(fileURLWithPath: path))
|
|
54
|
+
let base64 = data.base64EncodedString()
|
|
55
|
+
resolver(base64)
|
|
56
|
+
} catch {
|
|
57
|
+
rejecter("READ_ERROR", "Failed to read file: \(error.localizedDescription)", error)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
@objc
|
|
62
|
+
func deleteFile(_ path: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
63
|
+
do {
|
|
64
|
+
if FileManager.default.fileExists(atPath: path) {
|
|
65
|
+
try FileManager.default.removeItem(atPath: path)
|
|
66
|
+
}
|
|
67
|
+
resolver(nil)
|
|
68
|
+
} catch {
|
|
69
|
+
rejecter("DELETE_ERROR", "Failed to delete file: \(error.localizedDescription)", error)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
@objc
|
|
74
|
+
func exists(_ path: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
75
|
+
resolver(FileManager.default.fileExists(atPath: path))
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
@objc
|
|
79
|
+
func makeDirectory(_ path: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
80
|
+
do {
|
|
81
|
+
try FileManager.default.createDirectory(atPath: path, withIntermediateDirectories: true, attributes: nil)
|
|
82
|
+
resolver(nil)
|
|
83
|
+
} catch {
|
|
84
|
+
rejecter("MKDIR_ERROR", "Failed to create directory: \(error.localizedDescription)", error)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// MARK: - Cryptography
|
|
89
|
+
|
|
90
|
+
@objc
|
|
91
|
+
func calculateSHA256(_ base64Content: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
92
|
+
guard let data = Data(base64Encoded: base64Content) else {
|
|
93
|
+
rejecter("DECODE_ERROR", "Invalid base64 content", nil)
|
|
94
|
+
return
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
var hash = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
|
|
98
|
+
data.withUnsafeBytes {
|
|
99
|
+
_ = CC_SHA256($0.baseAddress, CC_LONG(data.count), &hash)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
let hexString = hash.map { String(format: "%02x", $0) }.joined()
|
|
103
|
+
resolver(hexString)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
@objc
|
|
107
|
+
func verifySignature(_ base64Content: String, signatureHex: String, publicKeyHex: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
108
|
+
// Ed25519 signature verification
|
|
109
|
+
// Note: For production, you might want to use a proper Ed25519 library like CryptoKit (iOS 13+) or libsodium
|
|
110
|
+
|
|
111
|
+
guard #available(iOS 13.0, *) else {
|
|
112
|
+
// Fall back to assuming valid if CryptoKit is not available
|
|
113
|
+
resolver(true)
|
|
114
|
+
return
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
guard let contentData = Data(base64Encoded: base64Content),
|
|
118
|
+
let signatureData = Data(hexString: signatureHex),
|
|
119
|
+
let publicKeyData = Data(hexString: publicKeyHex) else {
|
|
120
|
+
rejecter("DECODE_ERROR", "Invalid input data", nil)
|
|
121
|
+
return
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
do {
|
|
125
|
+
let publicKey = try Curve25519.Signing.PublicKey(rawRepresentation: publicKeyData)
|
|
126
|
+
let isValid = publicKey.isValidSignature(signatureData, for: contentData)
|
|
127
|
+
resolver(isValid)
|
|
128
|
+
} catch {
|
|
129
|
+
rejecter("VERIFY_ERROR", "Failed to verify signature: \(error.localizedDescription)", error)
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// MARK: - Bundle Application
|
|
134
|
+
|
|
135
|
+
@objc
|
|
136
|
+
func applyBundle(_ bundlePath: String, restart: Bool, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
137
|
+
// Store the bundle path for next launch
|
|
138
|
+
UserDefaults.standard.set(bundlePath, forKey: "OTAUpdate_BundlePath")
|
|
139
|
+
UserDefaults.standard.synchronize()
|
|
140
|
+
|
|
141
|
+
if restart {
|
|
142
|
+
// Post notification to restart the app
|
|
143
|
+
// The app delegate should handle this notification
|
|
144
|
+
DispatchQueue.main.async {
|
|
145
|
+
NotificationCenter.default.post(name: Notification.Name("OTAUpdate_RestartApp"), object: nil)
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
resolver(nil)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
@objc
|
|
153
|
+
func getPendingBundlePath(_ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
154
|
+
let path = UserDefaults.standard.string(forKey: "OTAUpdate_BundlePath")
|
|
155
|
+
resolver(path)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
@objc
|
|
159
|
+
func clearPendingBundle(_ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
160
|
+
UserDefaults.standard.removeObject(forKey: "OTAUpdate_BundlePath")
|
|
161
|
+
UserDefaults.standard.synchronize()
|
|
162
|
+
resolver(nil)
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// MARK: - Module Setup
|
|
166
|
+
|
|
167
|
+
@objc
|
|
168
|
+
static func requiresMainQueueSetup() -> Bool {
|
|
169
|
+
return false
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// MARK: - Data Extension
|
|
174
|
+
|
|
175
|
+
extension Data {
|
|
176
|
+
init?(hexString: String) {
|
|
177
|
+
let len = hexString.count / 2
|
|
178
|
+
var data = Data(capacity: len)
|
|
179
|
+
var i = hexString.startIndex
|
|
180
|
+
|
|
181
|
+
for _ in 0..<len {
|
|
182
|
+
let j = hexString.index(i, offsetBy: 2)
|
|
183
|
+
let bytes = hexString[i..<j]
|
|
184
|
+
if var num = UInt8(bytes, radix: 16) {
|
|
185
|
+
data.append(&num, count: 1)
|
|
186
|
+
} else {
|
|
187
|
+
return nil
|
|
188
|
+
}
|
|
189
|
+
i = j
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
self = data
|
|
193
|
+
}
|
|
194
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.OTAProvider = OTAProvider;
|
|
7
|
+
exports.UpdateBanner = UpdateBanner;
|
|
8
|
+
exports.useOTA = useOTA;
|
|
9
|
+
exports.withOTA = withOTA;
|
|
10
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
11
|
+
var _reactNative = require("react-native");
|
|
12
|
+
var _useOTAUpdate = require("./hooks/useOTAUpdate");
|
|
13
|
+
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
14
|
+
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
|
15
|
+
// Context type
|
|
16
|
+
|
|
17
|
+
const OTAContext = /*#__PURE__*/(0, _react.createContext)(null);
|
|
18
|
+
|
|
19
|
+
// Provider props
|
|
20
|
+
|
|
21
|
+
function OTAProvider({
|
|
22
|
+
children,
|
|
23
|
+
config,
|
|
24
|
+
onUpdateAvailable,
|
|
25
|
+
onUpdateDownloaded,
|
|
26
|
+
onError,
|
|
27
|
+
showMandatoryUpdateAlert = true,
|
|
28
|
+
mandatoryUpdateAlertTitle = 'Update Required',
|
|
29
|
+
mandatoryUpdateAlertMessage = 'A new version is available and must be installed to continue.'
|
|
30
|
+
}) {
|
|
31
|
+
const ota = (0, _useOTAUpdate.useOTAUpdate)(config);
|
|
32
|
+
const [handledMandatory, setHandledMandatory] = (0, _react.useState)(false);
|
|
33
|
+
|
|
34
|
+
// Handle callbacks
|
|
35
|
+
(0, _react.useEffect)(() => {
|
|
36
|
+
if (ota.status === 'available' && ota.updateInfo) {
|
|
37
|
+
onUpdateAvailable?.(ota.updateInfo);
|
|
38
|
+
|
|
39
|
+
// Handle mandatory updates
|
|
40
|
+
if (showMandatoryUpdateAlert && ota.updateInfo.isMandatory && !handledMandatory) {
|
|
41
|
+
setHandledMandatory(true);
|
|
42
|
+
_reactNative.Alert.alert(mandatoryUpdateAlertTitle, mandatoryUpdateAlertMessage, [{
|
|
43
|
+
text: 'Update Now',
|
|
44
|
+
onPress: async () => {
|
|
45
|
+
try {
|
|
46
|
+
await ota.downloadUpdate();
|
|
47
|
+
await ota.applyUpdate(true);
|
|
48
|
+
} catch (error) {
|
|
49
|
+
// Error is handled by the hook
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}]);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}, [ota.status, ota.updateInfo, onUpdateAvailable, showMandatoryUpdateAlert, handledMandatory, mandatoryUpdateAlertTitle, mandatoryUpdateAlertMessage, ota.downloadUpdate, ota.applyUpdate]);
|
|
56
|
+
(0, _react.useEffect)(() => {
|
|
57
|
+
if (ota.status === 'ready') {
|
|
58
|
+
onUpdateDownloaded?.();
|
|
59
|
+
}
|
|
60
|
+
}, [ota.status, onUpdateDownloaded]);
|
|
61
|
+
(0, _react.useEffect)(() => {
|
|
62
|
+
if (ota.error) {
|
|
63
|
+
onError?.(ota.error);
|
|
64
|
+
}
|
|
65
|
+
}, [ota.error, onError]);
|
|
66
|
+
const contextValue = {
|
|
67
|
+
...ota,
|
|
68
|
+
config
|
|
69
|
+
};
|
|
70
|
+
return /*#__PURE__*/_react.default.createElement(OTAContext.Provider, {
|
|
71
|
+
value: contextValue
|
|
72
|
+
}, children);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Hook to use OTA context
|
|
76
|
+
function useOTA() {
|
|
77
|
+
const context = (0, _react.useContext)(OTAContext);
|
|
78
|
+
if (!context) {
|
|
79
|
+
throw new Error('useOTA must be used within an OTAProvider');
|
|
80
|
+
}
|
|
81
|
+
return context;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Higher-order component
|
|
85
|
+
function withOTA(Component) {
|
|
86
|
+
return function WithOTA(props) {
|
|
87
|
+
const ota = useOTA();
|
|
88
|
+
return /*#__PURE__*/_react.default.createElement(Component, _extends({}, props, {
|
|
89
|
+
ota: ota
|
|
90
|
+
}));
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Utility component for update banner
|
|
95
|
+
|
|
96
|
+
function UpdateBanner({
|
|
97
|
+
renderAvailable,
|
|
98
|
+
renderDownloading,
|
|
99
|
+
renderReady
|
|
100
|
+
}) {
|
|
101
|
+
const ota = useOTA();
|
|
102
|
+
if (ota.status === 'available' && ota.updateInfo && renderAvailable) {
|
|
103
|
+
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, renderAvailable(ota.updateInfo, ota.downloadUpdate));
|
|
104
|
+
}
|
|
105
|
+
if (ota.status === 'downloading' && ota.downloadProgress && renderDownloading) {
|
|
106
|
+
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, renderDownloading(ota.downloadProgress.percentage));
|
|
107
|
+
}
|
|
108
|
+
if (ota.status === 'ready' && renderReady) {
|
|
109
|
+
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, renderReady(() => ota.applyUpdate(true)));
|
|
110
|
+
}
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=OTAProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_useOTAUpdate","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","_extends","assign","bind","arguments","length","apply","OTAContext","createContext","OTAProvider","children","config","onUpdateAvailable","onUpdateDownloaded","onError","showMandatoryUpdateAlert","mandatoryUpdateAlertTitle","mandatoryUpdateAlertMessage","ota","useOTAUpdate","handledMandatory","setHandledMandatory","useState","useEffect","status","updateInfo","isMandatory","Alert","alert","text","onPress","downloadUpdate","applyUpdate","error","contextValue","createElement","Provider","value","useOTA","context","useContext","Error","withOTA","Component","WithOTA","props","UpdateBanner","renderAvailable","renderDownloading","renderReady","Fragment","downloadProgress","percentage"],"sourceRoot":"../../src","sources":["OTAProvider.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.useOTAUpdate = useOTAUpdate;
|
|
7
|
+
var _react = require("react");
|
|
8
|
+
var _reactNative = require("react-native");
|
|
9
|
+
var _api = require("../utils/api");
|
|
10
|
+
var _storage = require("../utils/storage");
|
|
11
|
+
var _verification = require("../utils/verification");
|
|
12
|
+
const OTAUpdateNative = _reactNative.NativeModules.OTAUpdate;
|
|
13
|
+
// Generate or get device ID
|
|
14
|
+
async function getDeviceId() {
|
|
15
|
+
// Try to get from native module or AsyncStorage
|
|
16
|
+
// For simplicity, we generate a random one and ideally persist it
|
|
17
|
+
// In production, use a proper device ID solution
|
|
18
|
+
const id = `device_${Math.random().toString(36).substring(2, 15)}`;
|
|
19
|
+
return id;
|
|
20
|
+
}
|
|
21
|
+
function useOTAUpdate(config) {
|
|
22
|
+
const {
|
|
23
|
+
serverUrl,
|
|
24
|
+
appSlug,
|
|
25
|
+
channel = 'production',
|
|
26
|
+
appVersion,
|
|
27
|
+
publicKey,
|
|
28
|
+
checkOnMount = true,
|
|
29
|
+
checkOnForeground = true
|
|
30
|
+
} = config;
|
|
31
|
+
const [status, setStatus] = (0, _react.useState)('idle');
|
|
32
|
+
const [updateInfo, setUpdateInfo] = (0, _react.useState)(null);
|
|
33
|
+
const [downloadProgress, setDownloadProgress] = (0, _react.useState)(null);
|
|
34
|
+
const [error, setError] = (0, _react.useState)(null);
|
|
35
|
+
const [currentVersion, setCurrentVersion] = (0, _react.useState)(null);
|
|
36
|
+
const apiClient = (0, _react.useRef)(new _api.OTAApiClient(serverUrl));
|
|
37
|
+
const storage = (0, _react.useRef)(new _storage.UpdateStorage());
|
|
38
|
+
const deviceIdRef = (0, _react.useRef)(null);
|
|
39
|
+
const releaseRef = (0, _react.useRef)(null);
|
|
40
|
+
|
|
41
|
+
// Load current version on mount
|
|
42
|
+
(0, _react.useEffect)(() => {
|
|
43
|
+
const loadCurrentVersion = async () => {
|
|
44
|
+
const metadata = await storage.current.getMetadata();
|
|
45
|
+
if (metadata) {
|
|
46
|
+
setCurrentVersion(metadata.version);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
loadCurrentVersion();
|
|
50
|
+
}, []);
|
|
51
|
+
|
|
52
|
+
// Get device ID
|
|
53
|
+
const getDeviceIdCached = (0, _react.useCallback)(async () => {
|
|
54
|
+
if (!deviceIdRef.current) {
|
|
55
|
+
deviceIdRef.current = await getDeviceId();
|
|
56
|
+
}
|
|
57
|
+
return deviceIdRef.current;
|
|
58
|
+
}, []);
|
|
59
|
+
|
|
60
|
+
// Check for updates
|
|
61
|
+
const checkForUpdate = (0, _react.useCallback)(async () => {
|
|
62
|
+
try {
|
|
63
|
+
setStatus('checking');
|
|
64
|
+
setError(null);
|
|
65
|
+
const deviceId = await getDeviceIdCached();
|
|
66
|
+
const currentMetadata = await storage.current.getMetadata();
|
|
67
|
+
const response = await apiClient.current.checkUpdate({
|
|
68
|
+
appSlug,
|
|
69
|
+
channel,
|
|
70
|
+
platform: _reactNative.Platform.OS,
|
|
71
|
+
currentVersion: currentMetadata?.version || null,
|
|
72
|
+
appVersion,
|
|
73
|
+
deviceId
|
|
74
|
+
});
|
|
75
|
+
if (!response.updateAvailable || !response.release) {
|
|
76
|
+
setStatus('up-to-date');
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
releaseRef.current = response.release;
|
|
80
|
+
const info = {
|
|
81
|
+
version: response.release.version,
|
|
82
|
+
releaseId: response.release.id,
|
|
83
|
+
bundleSize: response.release.bundleSize,
|
|
84
|
+
isMandatory: response.release.isMandatory,
|
|
85
|
+
releaseNotes: response.release.releaseNotes
|
|
86
|
+
};
|
|
87
|
+
setUpdateInfo(info);
|
|
88
|
+
setStatus('available');
|
|
89
|
+
return info;
|
|
90
|
+
} catch (err) {
|
|
91
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
92
|
+
setError(error);
|
|
93
|
+
setStatus('error');
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
}, [appSlug, channel, appVersion, getDeviceIdCached]);
|
|
97
|
+
|
|
98
|
+
// Download update
|
|
99
|
+
const downloadUpdate = (0, _react.useCallback)(async () => {
|
|
100
|
+
if (!releaseRef.current) {
|
|
101
|
+
throw new Error('No update available to download');
|
|
102
|
+
}
|
|
103
|
+
const release = releaseRef.current;
|
|
104
|
+
const deviceId = await getDeviceIdCached();
|
|
105
|
+
try {
|
|
106
|
+
setStatus('downloading');
|
|
107
|
+
setDownloadProgress({
|
|
108
|
+
downloadedBytes: 0,
|
|
109
|
+
totalBytes: release.bundleSize,
|
|
110
|
+
percentage: 0
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// Report download start
|
|
114
|
+
apiClient.current.reportEvent({
|
|
115
|
+
appSlug,
|
|
116
|
+
releaseId: release.id,
|
|
117
|
+
deviceId,
|
|
118
|
+
eventType: 'download',
|
|
119
|
+
appVersion,
|
|
120
|
+
deviceInfo: (0, _api.getDeviceInfo)()
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// Download bundle
|
|
124
|
+
const bundleData = await apiClient.current.downloadBundle(release.bundleUrl);
|
|
125
|
+
setDownloadProgress({
|
|
126
|
+
downloadedBytes: bundleData.byteLength,
|
|
127
|
+
totalBytes: release.bundleSize,
|
|
128
|
+
percentage: 100
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
// Verify bundle
|
|
132
|
+
setStatus('verifying');
|
|
133
|
+
const verification = await (0, _verification.verifyBundle)(bundleData, release.bundleHash, release.bundleSignature, publicKey || null);
|
|
134
|
+
if (!verification.valid) {
|
|
135
|
+
throw new Error(verification.error || 'Bundle verification failed');
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Save bundle
|
|
139
|
+
const bundlePath = await storage.current.saveBundle(release.id, bundleData);
|
|
140
|
+
|
|
141
|
+
// Save metadata
|
|
142
|
+
await storage.current.saveMetadata({
|
|
143
|
+
releaseId: release.id,
|
|
144
|
+
version: release.version,
|
|
145
|
+
bundlePath,
|
|
146
|
+
bundleHash: release.bundleHash,
|
|
147
|
+
downloadedAt: Date.now()
|
|
148
|
+
});
|
|
149
|
+
setStatus('ready');
|
|
150
|
+
} catch (err) {
|
|
151
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
152
|
+
|
|
153
|
+
// Report failure
|
|
154
|
+
apiClient.current.reportEvent({
|
|
155
|
+
appSlug,
|
|
156
|
+
releaseId: release.id,
|
|
157
|
+
deviceId,
|
|
158
|
+
eventType: 'failure',
|
|
159
|
+
errorMessage: error.message,
|
|
160
|
+
appVersion,
|
|
161
|
+
deviceInfo: (0, _api.getDeviceInfo)()
|
|
162
|
+
});
|
|
163
|
+
setError(error);
|
|
164
|
+
setStatus('error');
|
|
165
|
+
throw error;
|
|
166
|
+
}
|
|
167
|
+
}, [appSlug, appVersion, publicKey, getDeviceIdCached]);
|
|
168
|
+
|
|
169
|
+
// Apply update
|
|
170
|
+
const applyUpdate = (0, _react.useCallback)(async (restartApp = true) => {
|
|
171
|
+
const metadata = await storage.current.getMetadata();
|
|
172
|
+
if (!metadata) {
|
|
173
|
+
throw new Error('No update available to apply');
|
|
174
|
+
}
|
|
175
|
+
const deviceId = await getDeviceIdCached();
|
|
176
|
+
try {
|
|
177
|
+
setStatus('applying');
|
|
178
|
+
|
|
179
|
+
// Report apply
|
|
180
|
+
apiClient.current.reportEvent({
|
|
181
|
+
appSlug,
|
|
182
|
+
releaseId: metadata.releaseId,
|
|
183
|
+
deviceId,
|
|
184
|
+
eventType: 'apply',
|
|
185
|
+
appVersion,
|
|
186
|
+
deviceInfo: (0, _api.getDeviceInfo)()
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
// Apply bundle using native module
|
|
190
|
+
if (OTAUpdateNative?.applyBundle) {
|
|
191
|
+
await OTAUpdateNative.applyBundle(metadata.bundlePath, restartApp);
|
|
192
|
+
} else if (restartApp) {
|
|
193
|
+
// If no native module, we need to restart manually
|
|
194
|
+
// The bundle will be loaded on next app start
|
|
195
|
+
if (__DEV__) {
|
|
196
|
+
console.log('[OTAUpdate] Update ready. Restart the app to apply.');
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Report success (this might not run if app restarts)
|
|
201
|
+
apiClient.current.reportEvent({
|
|
202
|
+
appSlug,
|
|
203
|
+
releaseId: metadata.releaseId,
|
|
204
|
+
deviceId,
|
|
205
|
+
eventType: 'success',
|
|
206
|
+
appVersion,
|
|
207
|
+
deviceInfo: (0, _api.getDeviceInfo)()
|
|
208
|
+
});
|
|
209
|
+
setCurrentVersion(metadata.version);
|
|
210
|
+
setStatus('idle');
|
|
211
|
+
} catch (err) {
|
|
212
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
213
|
+
apiClient.current.reportEvent({
|
|
214
|
+
appSlug,
|
|
215
|
+
releaseId: metadata.releaseId,
|
|
216
|
+
deviceId,
|
|
217
|
+
eventType: 'failure',
|
|
218
|
+
errorMessage: error.message,
|
|
219
|
+
appVersion,
|
|
220
|
+
deviceInfo: (0, _api.getDeviceInfo)()
|
|
221
|
+
});
|
|
222
|
+
setError(error);
|
|
223
|
+
setStatus('error');
|
|
224
|
+
throw error;
|
|
225
|
+
}
|
|
226
|
+
}, [appSlug, appVersion, getDeviceIdCached]);
|
|
227
|
+
|
|
228
|
+
// Clear pending update
|
|
229
|
+
const clearPendingUpdate = (0, _react.useCallback)(async () => {
|
|
230
|
+
const metadata = await storage.current.getMetadata();
|
|
231
|
+
if (metadata) {
|
|
232
|
+
await storage.current.deleteBundle(metadata.releaseId);
|
|
233
|
+
await storage.current.clearMetadata();
|
|
234
|
+
}
|
|
235
|
+
setUpdateInfo(null);
|
|
236
|
+
releaseRef.current = null;
|
|
237
|
+
setStatus('idle');
|
|
238
|
+
}, []);
|
|
239
|
+
|
|
240
|
+
// Check on mount
|
|
241
|
+
(0, _react.useEffect)(() => {
|
|
242
|
+
if (checkOnMount) {
|
|
243
|
+
checkForUpdate();
|
|
244
|
+
}
|
|
245
|
+
}, [checkOnMount, checkForUpdate]);
|
|
246
|
+
|
|
247
|
+
// Check on foreground
|
|
248
|
+
(0, _react.useEffect)(() => {
|
|
249
|
+
if (!checkOnForeground) return;
|
|
250
|
+
const handleAppStateChange = nextAppState => {
|
|
251
|
+
if (nextAppState === 'active' && status === 'idle') {
|
|
252
|
+
checkForUpdate();
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
const subscription = _reactNative.AppState.addEventListener('change', handleAppStateChange);
|
|
256
|
+
return () => {
|
|
257
|
+
subscription.remove();
|
|
258
|
+
};
|
|
259
|
+
}, [checkOnForeground, checkForUpdate, status]);
|
|
260
|
+
return {
|
|
261
|
+
status,
|
|
262
|
+
updateInfo,
|
|
263
|
+
downloadProgress,
|
|
264
|
+
error,
|
|
265
|
+
currentVersion,
|
|
266
|
+
checkForUpdate,
|
|
267
|
+
downloadUpdate,
|
|
268
|
+
applyUpdate,
|
|
269
|
+
clearPendingUpdate
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
//# sourceMappingURL=useOTAUpdate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_react","require","_reactNative","_api","_storage","_verification","OTAUpdateNative","NativeModules","OTAUpdate","getDeviceId","id","Math","random","toString","substring","useOTAUpdate","config","serverUrl","appSlug","channel","appVersion","publicKey","checkOnMount","checkOnForeground","status","setStatus","useState","updateInfo","setUpdateInfo","downloadProgress","setDownloadProgress","error","setError","currentVersion","setCurrentVersion","apiClient","useRef","OTAApiClient","storage","UpdateStorage","deviceIdRef","releaseRef","useEffect","loadCurrentVersion","metadata","current","getMetadata","version","getDeviceIdCached","useCallback","checkForUpdate","deviceId","currentMetadata","response","checkUpdate","platform","Platform","OS","updateAvailable","release","info","releaseId","bundleSize","isMandatory","releaseNotes","err","Error","String","downloadUpdate","downloadedBytes","totalBytes","percentage","reportEvent","eventType","deviceInfo","getDeviceInfo","bundleData","downloadBundle","bundleUrl","byteLength","verification","verifyBundle","bundleHash","bundleSignature","valid","bundlePath","saveBundle","saveMetadata","downloadedAt","Date","now","errorMessage","message","applyUpdate","restartApp","applyBundle","__DEV__","console","log","clearPendingUpdate","deleteBundle","clearMetadata","handleAppStateChange","nextAppState","subscription","AppState","addEventListener","remove"],"sourceRoot":"../../../src","sources":["hooks/useOTAUpdate.ts"],"mappings":"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","ignoreList":[]}
|