@functionland/react-native-fula 1.55.2 → 1.55.12
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/build.gradle +1 -1
- package/ios/Fula.mm +262 -248
- package/ios/Fula.swift +2207 -2064
- package/package.json +1 -1
- package/react-native-fula.podspec +2 -2
package/ios/Fula.swift
CHANGED
|
@@ -1,2064 +1,2207 @@
|
|
|
1
|
-
import Foundation
|
|
2
|
-
import Foundation.NSDate // for TimeInterval
|
|
3
|
-
import CommonCrypto
|
|
4
|
-
import Wnfs
|
|
5
|
-
import Fula
|
|
6
|
-
import os.log
|
|
7
|
-
|
|
8
|
-
extension OSLog {
|
|
9
|
-
|
|
10
|
-
private static var subsystem = Bundle.main.bundleIdentifier!
|
|
11
|
-
|
|
12
|
-
/// Logs the view cycles like a view that appeared.
|
|
13
|
-
static let viewCycle = OSLog(subsystem: subsystem, category: "viewcycle")
|
|
14
|
-
|
|
15
|
-
/// All logs related to tracking and analytics.
|
|
16
|
-
static let statistics = OSLog(subsystem: subsystem, category: "statistics")
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
extension OSLog {
|
|
20
|
-
|
|
21
|
-
func info(_ msg: String, _ args: CVarArg...) {
|
|
22
|
-
os_log("%{public}@", log: self, type: .info, msg)
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
func error(_ msg: String, _ args: CVarArg...) {
|
|
26
|
-
os_log("%{public}@", log: self, type: .error, msg)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// ... (more methods for different log levels, if needed)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
@objc(FulaModule)
|
|
34
|
-
class FulaModule: NSObject {
|
|
35
|
-
public let NAME: String = "FulaModule"
|
|
36
|
-
var fula: FulamobileClient?
|
|
37
|
-
|
|
38
|
-
var client: Client?
|
|
39
|
-
var wnfs: Wnfs?
|
|
40
|
-
var fulaConfig: FulamobileConfig?
|
|
41
|
-
var appDir: URL
|
|
42
|
-
var fulaStorePath: String
|
|
43
|
-
// Related to the Wnfs library
|
|
44
|
-
var rootCid: Cid?
|
|
45
|
-
var wnfsKey: Data?
|
|
46
|
-
let userDataHelper = UserDataHelper()
|
|
47
|
-
var secretKeyGlobal: Array<UInt8>?
|
|
48
|
-
var identityEncryptedGlobal: String?
|
|
49
|
-
static let PRIVATE_KEY_STORE_ID = "PRIVATE_KEY"
|
|
50
|
-
|
|
51
|
-
// FIXME: Hardcoded ,fula should remove all the codec arguments as the rs-wnfs library removed its usage now.
|
|
52
|
-
static let CODEC_DAG_CBOR = Int(113)
|
|
53
|
-
|
|
54
|
-
enum MyError: Error {
|
|
55
|
-
case runtimeError(String)
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
@objc(Client)
|
|
59
|
-
public class Client: NSObject {
|
|
60
|
-
let internalClient: FulamobileClient
|
|
61
|
-
|
|
62
|
-
init(clientInput: FulamobileClient) {
|
|
63
|
-
internalClient = clientInput
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
func get(_ cid: Data) throws -> Data {
|
|
67
|
-
do {
|
|
68
|
-
print(String(format: "ReactNative get cid: %s", cid.toHex()))
|
|
69
|
-
return try internalClient.get(cid)
|
|
70
|
-
} catch let error {
|
|
71
|
-
throw error
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
func put(_ cid: Data, _ data: Data) throws -> Void {
|
|
76
|
-
do {
|
|
77
|
-
print(String(format: "ReactNative put(%s) data: %s", cid.toHex(), data.toHex()))
|
|
78
|
-
try internalClient.put(data, codec: 0xFF & Int64(cid[1]))
|
|
79
|
-
} catch let error {
|
|
80
|
-
print("ReactNative put: ", error.localizedDescription)
|
|
81
|
-
throw error
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
override init() {
|
|
86
|
-
|
|
87
|
-
self.appDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
|
|
88
|
-
let fulaStoreURL = appDir.appendingPathComponent("/fula")
|
|
89
|
-
|
|
90
|
-
self.fulaStorePath = fulaStoreURL.path
|
|
91
|
-
let fileManager = FileManager.default
|
|
92
|
-
var success = true
|
|
93
|
-
if !fileManager.fileExists(atPath: fulaStorePath) {
|
|
94
|
-
do{
|
|
95
|
-
try fileManager.createDirectory(atPath: fulaStorePath, withIntermediateDirectories: true)
|
|
96
|
-
}catch let error{
|
|
97
|
-
print(error.localizedDescription)
|
|
98
|
-
success = false
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
if success {
|
|
103
|
-
print("Fula store folder created")
|
|
104
|
-
} else {
|
|
105
|
-
print("Unable to create fula store folder!")
|
|
106
|
-
|
|
107
|
-
}
|
|
108
|
-
super.init()
|
|
109
|
-
|
|
110
|
-
}
|
|
111
|
-
func convertConfigToJson(config: Cid) -> String {
|
|
112
|
-
return String(format: "{\"cid\": \"%@\"}", config)
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
func getName() -> String {
|
|
116
|
-
return NAME
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
func toByte(_ input: String) -> Data {
|
|
120
|
-
return input.data(using: .utf8)!
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
func stringArrToIntArr(_ s: Array<String>) -> Array<Int> {
|
|
125
|
-
return s.map { Int($0)!}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
func convertIntToByte(_ s: Array<Int>) -> Array<UInt8> {
|
|
129
|
-
return s.map { UInt8(exactly: $0)!}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
func convertStringToByte(_ input: String) -> Array<UInt8> {
|
|
133
|
-
let splitted = input.split(separator: ",").map { String($0) }
|
|
134
|
-
let keyInt = stringArrToIntArr(splitted)
|
|
135
|
-
return convertIntToByte(keyInt)
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
@objc func applicationWillResignActive() {
|
|
139
|
-
// Log that the app will resign active
|
|
140
|
-
os_log("Application will resign active", log: OSLog.viewCycle, type: .info)
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
@objc func applicationDidEnterBackground() {
|
|
144
|
-
// Log that the app has entered the background
|
|
145
|
-
os_log("Application did enter background", log: OSLog.viewCycle, type: .info)
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
@objc func applicationWillTerminate() {
|
|
149
|
-
// Attempt to shut down Fula cleanly (similar to onHostDestroy)
|
|
150
|
-
os_log("Application will terminate - shutting down Fula", log: OSLog.viewCycle, type: .info)
|
|
151
|
-
do {
|
|
152
|
-
if let fulaClient = self.fula {
|
|
153
|
-
try fulaClient.shutdown()
|
|
154
|
-
os_log("Fula shutdown successfully.", log: OSLog.viewCycle, type: .info)
|
|
155
|
-
}
|
|
156
|
-
} catch {
|
|
157
|
-
os_log("Error shutting down Fula: %{public}@", log: OSLog.viewCycle, type: .error, String(describing: error))
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
@objc(registerLifecycleListener:withRejecter:)
|
|
162
|
-
func registerLifecycleListener(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
163
|
-
NotificationCenter.default.addObserver(
|
|
164
|
-
self,
|
|
165
|
-
selector: #selector(applicationWillResignActive),
|
|
166
|
-
name: UIApplication.willResignActiveNotification,
|
|
167
|
-
object: nil)
|
|
168
|
-
|
|
169
|
-
NotificationCenter.default.addObserver(
|
|
170
|
-
self,
|
|
171
|
-
selector: #selector(applicationDidEnterBackground),
|
|
172
|
-
name: UIApplication.didEnterBackgroundNotification,
|
|
173
|
-
object: nil)
|
|
174
|
-
|
|
175
|
-
NotificationCenter.default.addObserver(
|
|
176
|
-
self,
|
|
177
|
-
selector: #selector(applicationWillTerminate),
|
|
178
|
-
name: UIApplication.willTerminateNotification,
|
|
179
|
-
object: nil)
|
|
180
|
-
|
|
181
|
-
// Assuming the operation is always successful
|
|
182
|
-
resolve(true)
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
deinit {
|
|
186
|
-
NotificationCenter.default.removeObserver(self)
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
@objc(checkConnection:withResolver:withRejecter:)
|
|
190
|
-
func checkConnection(timeout: NSNumber, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
191
|
-
NSLog("ReactNative checkConnection started with timeout=\(timeout)")
|
|
192
|
-
|
|
193
|
-
if let timeoutInt = timeout as? Int {
|
|
194
|
-
if self.fula != nil {
|
|
195
|
-
DispatchQueue.global(qos: .default).async {
|
|
196
|
-
do {
|
|
197
|
-
let connectionStatus = try self.checkConnectionInternal(timeout: timeoutInt)
|
|
198
|
-
NSLog("ReactNative checkConnection ended \(connectionStatus)")
|
|
199
|
-
resolve(connectionStatus)
|
|
200
|
-
}
|
|
201
|
-
catch let error {
|
|
202
|
-
NSLog("ReactNative checkConnection failed with Error: \(error.localizedDescription)")
|
|
203
|
-
resolve(false)
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
} else {
|
|
207
|
-
NSLog("ReactNative checkConnection fula is null")
|
|
208
|
-
resolve(false)
|
|
209
|
-
}
|
|
210
|
-
} else {
|
|
211
|
-
OSLog.viewCycle.error("ReactNative checkConnection - invalid timeout value")
|
|
212
|
-
reject("ERR_INVALID_TIMEOUT", "Invalid timeout value", nil)
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
@objc(newClient:withStorePath:withBloxAddr:withExchange:withAutoFlush:withUseRelay:withRefresh:withResolver:withRejecter:)
|
|
218
|
-
func newClient(identityString: String, storePath: String, bloxAddr: String, exchange: String, autoFlush: Bool, useRelay: Bool, refresh: Bool, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
219
|
-
print("ReactNative", "newClient storePath= " , storePath , " bloxAddr= " , bloxAddr , " exchange= " , exchange , " autoFlush= " , autoFlush , " useRelay= " , useRelay , " refresh= " , refresh)
|
|
220
|
-
do {
|
|
221
|
-
print("ReactNative", "newClient storePath= ", storePath)
|
|
222
|
-
let identity = toByte(identityString)
|
|
223
|
-
print("ReactNative", "newClient identity= ", identityString)
|
|
224
|
-
try newClientInternal(identity: identity, storePath: storePath, bloxAddr: bloxAddr, exchange: exchange, autoFlush: autoFlush, useRelay: useRelay, refresh: refresh)
|
|
225
|
-
let peerId = self.fula?.id_()
|
|
226
|
-
resolve(peerId)
|
|
227
|
-
} catch let error {
|
|
228
|
-
print("ReactNative", "newClient failed with Error: ", error.localizedDescription)
|
|
229
|
-
reject("ERR_FULA", "Can't create client", error)
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
@objc(isReady:withResolver:withRejecter:)
|
|
235
|
-
func isReady(filesystemCheck: Bool, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void{
|
|
236
|
-
print("ReactNative", "isReady started")
|
|
237
|
-
var initialized = false
|
|
238
|
-
do {
|
|
239
|
-
if (self.fula != nil && !self.fula!.id_().isEmpty) {
|
|
240
|
-
if (filesystemCheck) {
|
|
241
|
-
if (self.client != nil && rootCid != nil && !rootCid!.isEmpty) {
|
|
242
|
-
initialized = true
|
|
243
|
-
}
|
|
244
|
-
} else {
|
|
245
|
-
initialized = true
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
resolve(initialized)
|
|
249
|
-
} catch let error {
|
|
250
|
-
print("ReactNative", "isReady failed with Error: " + error.localizedDescription)
|
|
251
|
-
reject("ERR_FULA", "Check if fula is ready", error)
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
//TODO: we should consider refactor the name of this \
|
|
256
|
-
// function to be compatible with the android version.
|
|
257
|
-
@objc(initFula:withStorePath:withBloxAddr:withExchange:withAutoFlush:withRootConfig:withUseRelay:withRefresh:withResolver:withRejecter:)
|
|
258
|
-
func initFula(identityString: String, storePath: String, bloxAddr: String, exchange: String, autoFlush: Bool, rootConfig: String, useRelay: Bool, refresh: Bool, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
259
|
-
|
|
260
|
-
NSLog("ReactNative - init started")
|
|
261
|
-
|
|
262
|
-
do {
|
|
263
|
-
|
|
264
|
-
var resultData = Dictionary<String, String>()
|
|
265
|
-
NSLog("ReactNative init storePath= \(storePath)")
|
|
266
|
-
let identity = self.toByte(identityString)
|
|
267
|
-
NSLog("ReactNative init identity= \(identityString)")
|
|
268
|
-
let obj = try initInternal(identity: identity, storePath: storePath, bloxAddr: bloxAddr, exchange: exchange, autoFlush: autoFlush, _rootCid: rootConfig, useRelay: useRelay, refresh: refresh)
|
|
269
|
-
NSLog("ReactNative init object created: [ \(obj[0]), \(obj[1]), \(obj[2]) ]")
|
|
270
|
-
resultData["peerId"] = obj[0]
|
|
271
|
-
resultData["rootCid"] = obj[1]
|
|
272
|
-
resultData["wnfs_key"] = obj[2]
|
|
273
|
-
resolve(resultData as NSDictionary)
|
|
274
|
-
|
|
275
|
-
} catch let error {
|
|
276
|
-
NSLog("ReactNative init failed with Error: \(error.localizedDescription)")
|
|
277
|
-
reject("ERR_FULA", "init failed", error)
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
@objc(logout:withStorePath:withResolver:withRejecter:)
|
|
283
|
-
func logout(identityString: String, storePath: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void{
|
|
284
|
-
|
|
285
|
-
print("ReactNative", "logout started")
|
|
286
|
-
do {
|
|
287
|
-
let identity = toByte(identityString)
|
|
288
|
-
try logoutInternal(identity: identity, _storePath: storePath)
|
|
289
|
-
print("ReactNative", "logout completed")
|
|
290
|
-
resolve("")
|
|
291
|
-
|
|
292
|
-
} catch let error {
|
|
293
|
-
print("ReactNative", "logout failed with Error: ", error.localizedDescription)
|
|
294
|
-
reject("ERR_FULA", "logout failed", error)
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
func checkConnectionInternal(timeout: Int) throws -> Bool {
|
|
300
|
-
NSLog("ReactNative checkConnectionInternal started with timeout: \(timeout)")
|
|
301
|
-
var connectionStatus = false
|
|
302
|
-
|
|
303
|
-
if let fula = self.fula {
|
|
304
|
-
let semaphore = DispatchSemaphore(value: 0)
|
|
305
|
-
let queue = DispatchQueue(label: "com.yourapp.checkConnection", attributes: .concurrent)
|
|
306
|
-
|
|
307
|
-
queue.async {
|
|
308
|
-
do {
|
|
309
|
-
NSLog("ReactNative connectToBlox started")
|
|
310
|
-
try fula.connectToBlox()
|
|
311
|
-
connectionStatus = true
|
|
312
|
-
NSLog("ReactNative checkConnectionInternal succeeded")
|
|
313
|
-
semaphore.signal()
|
|
314
|
-
} catch let error {
|
|
315
|
-
NSLog("ReactNative checkConnectionInternal failed with Error: \(error.localizedDescription)")
|
|
316
|
-
semaphore.signal()
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
let timeoutResult = semaphore.wait(timeout: .now() + .seconds(timeout))
|
|
321
|
-
switch timeoutResult {
|
|
322
|
-
case .timedOut:
|
|
323
|
-
NSLog("ReactNative checkConnectionInternal timed out")
|
|
324
|
-
return false
|
|
325
|
-
case .success:
|
|
326
|
-
return connectionStatus
|
|
327
|
-
}
|
|
328
|
-
} else {
|
|
329
|
-
NSLog("ReactNative checkConnectionInternal failed because fula is not initialized")
|
|
330
|
-
return false
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
@objc(checkFailedActions:withTimeout:withResolver:withRejecter:)
|
|
335
|
-
func checkFailedActions(retry: Bool, timeout: Int, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
|
|
336
|
-
do {
|
|
337
|
-
guard let fula = self.fula else {
|
|
338
|
-
throw NSError(domain: "ERR_FULA", code: 1001, userInfo: [NSLocalizedDescriptionKey: "Fula is not initialized"])
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
if !retry {
|
|
342
|
-
NSLog("ReactNative checkFailedActions without retry")
|
|
343
|
-
let failedLinks = try fula.listFailedPushes()
|
|
344
|
-
|
|
345
|
-
let nextFailedLink = try failedLinks.next()
|
|
346
|
-
if nextFailedLink != nil {
|
|
347
|
-
// Assuming nextFailedLink is of type Data; replace `toHex()` with an appropriate method to convert Data to a hex string
|
|
348
|
-
NSLog("ReactNative checkFailedActions found")
|
|
349
|
-
resolve(true)
|
|
350
|
-
} else {
|
|
351
|
-
resolve(false)
|
|
352
|
-
}
|
|
353
|
-
} else {
|
|
354
|
-
NSLog("ReactNative checkFailedActions with retry")
|
|
355
|
-
let retryResults = try retryFailedActionsInternal(timeout: timeout) // Ensure retryFailedActionsInternal accepts a timeout parameter
|
|
356
|
-
resolve(!retryResults)
|
|
357
|
-
}
|
|
358
|
-
} catch let error {
|
|
359
|
-
NSLog("ReactNative checkFailedActions failed with Error: \(error.localizedDescription)")
|
|
360
|
-
reject("ERR_FULA", "CheckFailedActions failed", error)
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
func retryFailedActionsInternal(timeout: Int) throws -> Bool {
|
|
367
|
-
NSLog("ReactNative retryFailedActionsInternal started")
|
|
368
|
-
|
|
369
|
-
guard let fula = self.fula else {
|
|
370
|
-
NSLog("ReactNative retryFailedActionsInternal failed because fula is not initialized")
|
|
371
|
-
return false
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
do {
|
|
375
|
-
let connectionCheck = try checkConnectionInternal(timeout: timeout)
|
|
376
|
-
|
|
377
|
-
if connectionCheck {
|
|
378
|
-
do {
|
|
379
|
-
NSLog("ReactNative retryFailedPushes started")
|
|
380
|
-
try fula.retryFailedPushes()
|
|
381
|
-
NSLog("ReactNative flush started")
|
|
382
|
-
try fula.flush()
|
|
383
|
-
return true
|
|
384
|
-
} catch let error {
|
|
385
|
-
try fula.flush()
|
|
386
|
-
NSLog("ReactNative retryFailedActionsInternal failed with Error: \(error.localizedDescription)")
|
|
387
|
-
return false
|
|
388
|
-
}
|
|
389
|
-
} else {
|
|
390
|
-
NSLog("ReactNative retryFailedActionsInternal failed because blox is offline")
|
|
391
|
-
return false
|
|
392
|
-
}
|
|
393
|
-
} catch let error {
|
|
394
|
-
NSLog("ReactNative retryFailedActionsInternal failed with Error: \(error.localizedDescription)")
|
|
395
|
-
return false
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
func createPeerIdentity(privateKey: Data) throws -> Data {
|
|
400
|
-
let secretKey = try Cryptography.generateKey(privateKey)
|
|
401
|
-
|
|
402
|
-
var encryptedKey: String? = userDataHelper.getValue(FulaModule.PRIVATE_KEY_STORE_ID)
|
|
403
|
-
NSLog("ReactNative createPeerIdentity encryptedKey=\(encryptedKey ?? "nil")")
|
|
404
|
-
if encryptedKey == nil {
|
|
405
|
-
let privateKeyString = String(data: privateKey, encoding: .utf8) ?? ""
|
|
406
|
-
|
|
407
|
-
guard !privateKeyString.isEmpty else {
|
|
408
|
-
throw NSError(domain: "KeyGenerationError", code: -1, userInfo: [NSLocalizedDescriptionKey: "Private key string conversion failed"])
|
|
409
|
-
}
|
|
410
|
-
var error: NSError?
|
|
411
|
-
guard let autoGeneratedIdentity = FulamobileGenerateEd25519KeyFromString(privateKeyString, &error)?.toUint8Array() else {
|
|
412
|
-
throw error ?? NSError(domain: "KeyGenerationError", code: -1, userInfo: nil)
|
|
413
|
-
}
|
|
414
|
-
encryptedKey = try Cryptography.encryptMsg([UInt8](autoGeneratedIdentity), [UInt8](secretKey))
|
|
415
|
-
NSLog("ReactNative createPeerIdentity encryptedKey2=\(encryptedKey)")
|
|
416
|
-
userDataHelper.add(FulaModule.PRIVATE_KEY_STORE_ID, encryptedKey ?? "")
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
// Assuming decryptMsg returns Data or throws an error if decryption fails
|
|
420
|
-
guard let encryptedKeyData = encryptedKey, !encryptedKeyData.isEmpty else {
|
|
421
|
-
throw NSError(domain: "DecryptionError", code: -1, userInfo: [NSLocalizedDescriptionKey: "Encrypted key is empty"])
|
|
422
|
-
}
|
|
423
|
-
let decryptedData = try Cryptography.decryptMsg(encryptedKeyData, Array(secretKey))
|
|
424
|
-
let hexString = decryptedData.map { String(format: "%02hhx", $0) }.joined()
|
|
425
|
-
NSLog("ReactNative createPeerIdentity decryptedData=\(hexString)")
|
|
426
|
-
return Data(decryptedData)
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
func decryptLibp2pIdentity(_ encryptedLibp2pId: String, with encryptionSecretKey: Data) throws -> String {
|
|
430
|
-
// Convert Data to [UInt8]
|
|
431
|
-
let secretKeyBytes = [UInt8](encryptionSecretKey)
|
|
432
|
-
|
|
433
|
-
// Attempt decryption
|
|
434
|
-
guard let decryptedBytes = try? Cryptography.decryptMsg(encryptedLibp2pId, secretKeyBytes) else {
|
|
435
|
-
throw NSError(domain: "DecryptionError", code: 1, userInfo: [NSLocalizedDescriptionKey: "Failed to decrypt Libp2p ID"])
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
// Assuming decryptedBytes is an array of UInt8
|
|
439
|
-
return String(decoding: decryptedBytes, as: UTF8.self)
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
func createEncryptedLibp2pId(from identity: Data, with encryptionSecretKey: Data) throws -> String {
|
|
443
|
-
var error: NSError?
|
|
444
|
-
guard let autoGeneratedIdentity = FulamobileGenerateEd25519Key(&error) else {
|
|
445
|
-
throw error ?? NSError(domain: "KeyGenerationError", code: -1, userInfo: nil)
|
|
446
|
-
}
|
|
447
|
-
let encryptedLibp2pId = try Cryptography.encryptMsg(Array(autoGeneratedIdentity), Array(encryptionSecretKey))
|
|
448
|
-
userDataHelper.add(FulaModule.PRIVATE_KEY_STORE_ID, encryptedLibp2pId)
|
|
449
|
-
return encryptedLibp2pId
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
func createNewrootCid(identity: Data) throws -> Void {
|
|
453
|
-
let hash32 = identity.sha256()
|
|
454
|
-
NSLog("ReactNative createNewrootCid wnfsKey= \(identity.toHex()) , hash32 = \(hash32.toHex())")
|
|
455
|
-
if (self.fula != nil) {
|
|
456
|
-
NSLog("ReactNative createNewrootCid self.fula not null")
|
|
457
|
-
try self.fula?.flush()
|
|
458
|
-
}
|
|
459
|
-
NSLog("ReactNative fula flushed")
|
|
460
|
-
rootCid = try self.wnfs?.Init(wnfsKey: hash32)
|
|
461
|
-
NSLog("ReactNative privateForest is created: \(rootCid!)")
|
|
462
|
-
wnfsKey = identity
|
|
463
|
-
NSLog("ReactNative rootCid is created: cid= \(rootCid!) wnfs_key= \(wnfsKey!.toHex()), hash32=\(hash32)")
|
|
464
|
-
try encryptAndStoreConfig()
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
func loadWnfs(_ _wnfsKey: Data , _ _rootCid: String) throws {
|
|
468
|
-
NSLog("ReactNative loadWnfs called: _rootCid=\(_rootCid)")
|
|
469
|
-
let hash32 = _wnfsKey.sha256()
|
|
470
|
-
NSLog("ReactNative wnfsKey= \(_wnfsKey.toHex()) ; hash32 = \(hash32.toHex())")
|
|
471
|
-
try self.wnfs?.LoadWithWNFSKey(wnfsKey: hash32, cid: _rootCid)
|
|
472
|
-
NSLog("ReactNative loadWnfs LoadWithWNFSKey")
|
|
473
|
-
rootCid = _rootCid
|
|
474
|
-
wnfsKey = _wnfsKey
|
|
475
|
-
NSLog("ReactNative loadWnfs called: rootCid=\(rootCid)")
|
|
476
|
-
if (self.fula != nil) {
|
|
477
|
-
try self.fula?.flush()
|
|
478
|
-
}
|
|
479
|
-
NSLog("ReactNative loadWnfs completed")
|
|
480
|
-
try encryptAndStoreConfig()
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
func encryptAndStoreConfig() throws {
|
|
485
|
-
do {
|
|
486
|
-
if let identityEncryptedGlobalUnwrapped = identityEncryptedGlobal {
|
|
487
|
-
NSLog("ReactNative encryptAndStoreConfig started")
|
|
488
|
-
|
|
489
|
-
if let rootCidUnwrapped = rootCid, let wnfsKeyUnwrapped = wnfsKey, let secretKeyGlobalUnwrapped = secretKeyGlobal {
|
|
490
|
-
NSLog("ReactNative encryptAndStoreConfig started with rootCid: \(rootCidUnwrapped.toUint8Array()) and wnfsKey:\(wnfsKeyUnwrapped)")
|
|
491
|
-
|
|
492
|
-
let cid_encrypted = try Cryptography.encryptMsg(rootCidUnwrapped.toUint8Array(), secretKeyGlobalUnwrapped)
|
|
493
|
-
NSLog("ReactNative encryptAndStoreConfig cid_encrypted: \(cid_encrypted)")
|
|
494
|
-
|
|
495
|
-
let wnfs_key_encrypted = try Cryptography.encryptMsg(wnfsKeyUnwrapped.toUint8Array(), secretKeyGlobalUnwrapped)
|
|
496
|
-
NSLog("ReactNative encryptAndStoreConfig wnfs_key_encrypted: \(wnfs_key_encrypted)")
|
|
497
|
-
|
|
498
|
-
userDataHelper.add("cid_encrypted_" + identityEncryptedGlobalUnwrapped, cid_encrypted)
|
|
499
|
-
userDataHelper.add("wnfs_key_encrypted_" + identityEncryptedGlobalUnwrapped, wnfs_key_encrypted)
|
|
500
|
-
} else {
|
|
501
|
-
// Handle the case where rootCid, wnfsKey, or secretKeyGlobal is nil
|
|
502
|
-
NSLog("ReactNative encryptAndStoreConfig failed because one of the values is nil")
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
} catch let error {
|
|
506
|
-
NSLog("ReactNative encryptAndStoreConfig failed with Error: \(error.localizedDescription)")
|
|
507
|
-
throw error
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
func logoutInternal(identity: Data, _storePath: String?) throws {
|
|
512
|
-
do {
|
|
513
|
-
if (self.fula != nil) {
|
|
514
|
-
try self.fula?.flush()
|
|
515
|
-
}
|
|
516
|
-
let secretKey = try Cryptography.generateKey(identity)
|
|
517
|
-
let identity_encrypted: String = try Cryptography.encryptMsg(identity.toUint8Array(), [UInt8](secretKey))
|
|
518
|
-
|
|
519
|
-
userDataHelper.remove("cid_encrypted_"+identity_encrypted)
|
|
520
|
-
|
|
521
|
-
//TODO: Should also remove peerid @Mahdi
|
|
522
|
-
|
|
523
|
-
userDataHelper.remove("cid_encrypted_"+identity_encrypted)
|
|
524
|
-
|
|
525
|
-
rootCid = nil
|
|
526
|
-
secretKeyGlobal = nil
|
|
527
|
-
identityEncryptedGlobal = nil
|
|
528
|
-
var storePath = _storePath
|
|
529
|
-
if (storePath == nil || storePath!.isEmpty) {
|
|
530
|
-
storePath = fulaStorePath
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
do{
|
|
534
|
-
try FileManager.default.removeItem(atPath: fulaStorePath)
|
|
535
|
-
}catch let error{
|
|
536
|
-
print("Deleting fula store path", error.localizedDescription)
|
|
537
|
-
throw error
|
|
538
|
-
}
|
|
539
|
-
} catch let error {
|
|
540
|
-
print("ReactNative", "logout internal failed with Error: ", error.localizedDescription)
|
|
541
|
-
throw error
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
func getFulaClient() -> FulamobileClient? {
|
|
546
|
-
return self.fula
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
func newClientInternal(identity: Data, storePath: String?, bloxAddr: String, exchange: String, autoFlush: Bool, useRelay: Bool, refresh: Bool) throws -> Void {
|
|
550
|
-
do {
|
|
551
|
-
NSLog("ReactNative fula newClientInternal refresh=\(refresh)")
|
|
552
|
-
fulaConfig = FulamobileConfig()
|
|
553
|
-
NSLog("ReactNative: cofig is set")
|
|
554
|
-
if (storePath == nil || storePath!.isEmpty) {
|
|
555
|
-
fulaConfig!.storePath = fulaStorePath
|
|
556
|
-
} else {
|
|
557
|
-
fulaConfig!.storePath = storePath!
|
|
558
|
-
}
|
|
559
|
-
NSLog("ReactNative storePath is set: \(fulaConfig!.storePath)")
|
|
560
|
-
|
|
561
|
-
let peerIdentity = try createPeerIdentity(privateKey: identity)
|
|
562
|
-
fulaConfig!.identity = peerIdentity
|
|
563
|
-
NSLog("ReactNative peerIdentity is set: \(fulaConfig!.identity!.toHex())")
|
|
564
|
-
fulaConfig!.bloxAddr = bloxAddr
|
|
565
|
-
NSLog("ReactNative bloxAddr is set: \(fulaConfig!.bloxAddr)")
|
|
566
|
-
fulaConfig!.exchange = exchange
|
|
567
|
-
fulaConfig!.syncWrites = autoFlush
|
|
568
|
-
if (useRelay) {
|
|
569
|
-
fulaConfig!.allowTransientConnection = true
|
|
570
|
-
fulaConfig!.forceReachabilityPrivate = true
|
|
571
|
-
}
|
|
572
|
-
if (self.fula == nil || refresh) {
|
|
573
|
-
NSLog("ReactNative Creating a new Fula instance")
|
|
574
|
-
do {
|
|
575
|
-
try shutdownInternal()
|
|
576
|
-
NSLog("ReactNative Creating a new Fula instance shutdown done")
|
|
577
|
-
var error: NSError?
|
|
578
|
-
let client = FulamobileNewClient(fulaConfig, &error)
|
|
579
|
-
if let error = error {
|
|
580
|
-
throw error
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
self.fula = client
|
|
584
|
-
NSLog("ReactNative FulamobileClient created")
|
|
585
|
-
if (self.fula != nil) {
|
|
586
|
-
NSLog("ReactNative Creating a new Fula instance fula is not null, flushing")
|
|
587
|
-
try self.fula?.flush()
|
|
588
|
-
} else {
|
|
589
|
-
NSLog("** ReactNative Creating a new Fula instance fula failed **")
|
|
590
|
-
}
|
|
591
|
-
} catch let error {
|
|
592
|
-
NSLog("ReactNative Failed to create new Fula instance: \(error.localizedDescription)")
|
|
593
|
-
throw MyError.runtimeError("ReactNative Failed to create new Fula instance")
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
NSLog("ReactNative peerIdentity returned: \(peerIdentity)")
|
|
597
|
-
} catch let error {
|
|
598
|
-
NSLog("ReactNative newclientInternal failed with Error: \(error.localizedDescription)")
|
|
599
|
-
throw error
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
func initInternal(identity: Data, storePath: String, bloxAddr: String, exchange: String, autoFlush: Bool, _rootCid: String, useRelay: Bool, refresh: Bool) throws -> [String] {
|
|
604
|
-
|
|
605
|
-
do {
|
|
606
|
-
os_log("ReactNative: This is an info message.", log: OSLog.viewCycle, type: .info)
|
|
607
|
-
NSLog("ReactNative: This is a simple log message.")
|
|
608
|
-
|
|
609
|
-
NSLog("ReactNative fula initInternal=\(refresh)")
|
|
610
|
-
if (self.fula == nil || refresh) {
|
|
611
|
-
NSLog("ReactNative fula self.fula is null or refresh is set")
|
|
612
|
-
try newClientInternal(identity: identity, storePath: storePath, bloxAddr: bloxAddr, exchange: exchange, autoFlush: autoFlush, useRelay: useRelay, refresh: refresh)
|
|
613
|
-
NSLog("ReactNative fula initialized")
|
|
614
|
-
if (self.fula == nil) {
|
|
615
|
-
NSLog("ReactNative: fula is not initialized")
|
|
616
|
-
}
|
|
617
|
-
guard let fulaId = self.fula?.id_() else {
|
|
618
|
-
NSLog("ReactNative error: fula is not initialized")
|
|
619
|
-
throw MyError.runtimeError("ReactNative: fula client not ready")
|
|
620
|
-
}
|
|
621
|
-
NSLog("ReactNative fula initialized: \(fulaId)")
|
|
622
|
-
}
|
|
623
|
-
if(self.client == nil || self.wnfs == nil || refresh) {
|
|
624
|
-
NSLog("ReactNative fula self.client is null or refresh is set")
|
|
625
|
-
self.client = Client(clientInput: self.fula!)
|
|
626
|
-
self.wnfs = Wnfs(putFn: { cid, data in
|
|
627
|
-
guard let c = self.client else {
|
|
628
|
-
NSLog("ReactNative wnfs put: fula client not ready")
|
|
629
|
-
throw MyError.runtimeError("ReactNative wnfs: fula client not ready")
|
|
630
|
-
}
|
|
631
|
-
try c.put(cid, data)
|
|
632
|
-
}, getFn: { cid in
|
|
633
|
-
guard let c = self.client else {
|
|
634
|
-
NSLog("ReactNative wnfs get: fula client not ready")
|
|
635
|
-
throw MyError.runtimeError("ReactNative wnfs: fula client not ready")
|
|
636
|
-
}
|
|
637
|
-
return try c.get(cid)
|
|
638
|
-
})
|
|
639
|
-
NSLog("ReactNative wnfs initialized")
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
let secretKey = try Cryptography.generateKey(identity)
|
|
643
|
-
let identity_encrypted = try Cryptography.encryptMsg(identity.toUint8Array(), [UInt8](secretKey))
|
|
644
|
-
|
|
645
|
-
identityEncryptedGlobal = identity_encrypted
|
|
646
|
-
secretKeyGlobal = [UInt8](secretKey)
|
|
647
|
-
|
|
648
|
-
if (rootCid == nil || rootCid!.isEmpty) {
|
|
649
|
-
NSLog("ReactNative rootCid is empty.")
|
|
650
|
-
//Load from keystore
|
|
651
|
-
|
|
652
|
-
let cid_encrypted_fetched = userDataHelper.getValue("cid_encrypted_"+identity_encrypted)
|
|
653
|
-
NSLog("ReactNative Here1")
|
|
654
|
-
var cid: Array<UInt8>? = nil
|
|
655
|
-
if(cid_encrypted_fetched != nil && !cid_encrypted_fetched!.isEmpty) {
|
|
656
|
-
NSLog("ReactNative decrypting cid= \(cid_encrypted_fetched!) with secret \(secretKey.toHex())")
|
|
657
|
-
cid = try Cryptography.decryptMsg(cid_encrypted_fetched!, [UInt8](secretKey))
|
|
658
|
-
|
|
659
|
-
}
|
|
660
|
-
NSLog("ReactNative Here2")
|
|
661
|
-
//print("ReactNative", "Attempted to fetch cid from keystore cid="+cid+" & wnfs_key="+wnfs_key)
|
|
662
|
-
if(cid == nil || cid!.isEmpty){
|
|
663
|
-
NSLog("ReactNative cid or wnfs key was not found")
|
|
664
|
-
if(!_rootCid.isEmpty){
|
|
665
|
-
NSLog("ReactNative Re-setting cid from input: \(_rootCid)")
|
|
666
|
-
cid = _rootCid.toUint8Array()
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
}
|
|
670
|
-
if(cid == nil || cid!.isEmpty){
|
|
671
|
-
NSLog("ReactNative Tried to recover cid but was not successful. Creating ones")
|
|
672
|
-
try createNewrootCid(identity: identity)
|
|
673
|
-
} else {
|
|
674
|
-
NSLog("ReactNative Found cid and wnfs key in keychain store")
|
|
675
|
-
NSLog("ReactNative Recovered cid and private ref from keychain store. cid=\(cid!) & wnfs_key=\(identity)")
|
|
676
|
-
try loadWnfs(identity, cid!.toData().toUTF8String()!)
|
|
677
|
-
}
|
|
678
|
-
NSLog("ReactNative creating/reloading rootCid completed")
|
|
679
|
-
|
|
680
|
-
/*
|
|
681
|
-
byte[] testbyte = convertStringToByte("-104,40,24,-93,24,100,24,114,24,111,24,111,24,116,24,-126,24,-126,0,0,24,-128,24,103,24,118,24,101,24,114,24,115,24,105,24,111,24,110,24,101,24,48,24,46,24,49,24,46,24,48,24,105,24,115,24,116,24,114,24,117,24,99,24,116,24,117,24,114,24,101,24,100,24,104,24,97,24,109,24,116")
|
|
682
|
-
long testcodec = 85
|
|
683
|
-
byte[] testputcid = client!.put(testbyte, testcodec)
|
|
684
|
-
print("ReactNative", "client!.put test done"+ Arrays.toString(testputcid))
|
|
685
|
-
byte[] testfetchedcid = convertStringToByte("1,113,18,32,-6,-63,-128,79,-102,-89,57,77,-8,67,-98,8,-81,40,-87,123,122,29,-52,-124,-60,-53,100,105,125,123,-5,-99,41,106,-124,-64")
|
|
686
|
-
byte[] testfetchedbytes = client!.get(testfetchedcid)
|
|
687
|
-
print("ReactNative", "client!.get test done"+ Arrays.toString(testfetchedbytes))
|
|
688
|
-
*/
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
NSLog("ReactNative rootCid is created: cid=\(self.rootCid!) & wnfs_key=\(self.wnfsKey!.toHex())")
|
|
692
|
-
} else {
|
|
693
|
-
NSLog("ReactNative rootCid existed: cid=\(self.rootCid!) & wnfs_key=\(self.wnfsKey!.toHex())")
|
|
694
|
-
}
|
|
695
|
-
guard let peerId = self.fula?.id_() else {
|
|
696
|
-
NSLog("ReactNative error: fula is not initialized")
|
|
697
|
-
throw MyError.runtimeError("ReactNative: fula client not ready")
|
|
698
|
-
}
|
|
699
|
-
NSLog("ReactNative fula peerId initialized: \(peerId)")
|
|
700
|
-
var obj = [String]()
|
|
701
|
-
obj.append(peerId)
|
|
702
|
-
obj.append(rootCid!)
|
|
703
|
-
obj.append(wnfsKey!.toHex())
|
|
704
|
-
NSLog("ReactNative initInternal is completed successfully")
|
|
705
|
-
if (self.fula != nil) {
|
|
706
|
-
try self.fula?.flush()
|
|
707
|
-
}
|
|
708
|
-
return obj
|
|
709
|
-
} catch let error {
|
|
710
|
-
NSLog("ReactNative init internal failed with Error: \(error.localizedDescription)")
|
|
711
|
-
throw error
|
|
712
|
-
}
|
|
713
|
-
}
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
@objc(mkdir:withResolver:withRejecter:)
|
|
717
|
-
func mkdir(path: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
718
|
-
NSLog("ReactNative mkdir: path = \(path)")
|
|
719
|
-
do {
|
|
720
|
-
let cid = try self.wnfs?.MkDir(cid: rootCid!, remotePath: path)
|
|
721
|
-
if(cid != nil) {
|
|
722
|
-
rootCid = cid
|
|
723
|
-
try encryptAndStoreConfig()
|
|
724
|
-
if (self.fula != nil) {
|
|
725
|
-
try self.fula?.flush()
|
|
726
|
-
}
|
|
727
|
-
resolve(rootCid)
|
|
728
|
-
} else {
|
|
729
|
-
NSLog("ReactNative mkdir Error: config is nil")
|
|
730
|
-
reject("ERR_WNFS", "Can't make dir", nil)
|
|
731
|
-
}
|
|
732
|
-
|
|
733
|
-
} catch let error{
|
|
734
|
-
print("mkdir", error.localizedDescription)
|
|
735
|
-
reject("ERR_WNFS", "mkdir", error)
|
|
736
|
-
}
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
@objc(writeFile:withLocalFilename:withResolver:withRejecter:)
|
|
740
|
-
func writeFile(fulaTargetFilename: String, localFilename: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
741
|
-
/*
|
|
742
|
-
// reads content of the file form localFilename (should include full absolute path to local file with read permission
|
|
743
|
-
// writes content to the specified location by fulaTargetFilename in Fula filesystem
|
|
744
|
-
// fulaTargetFilename: a string including full path and filename of target file on Fula (e.g. root/pictures/cat.jpg)
|
|
745
|
-
// localFilename: a string containing full path and filename of local file on hte device (e.g /usr/bin/cat.jpg)
|
|
746
|
-
// Returns: new cid of the root after this file is placed in the tree
|
|
747
|
-
*/
|
|
748
|
-
NSLog("ReactNative writeFile to : path = \(fulaTargetFilename) + from: \(localFilename)")
|
|
749
|
-
do {
|
|
750
|
-
let cid = try self.wnfs?.WriteFileFromPath(cid: rootCid!, remotePath: fulaTargetFilename, fileUrl: URL.init(string: localFilename)!)
|
|
751
|
-
if(cid != nil) {
|
|
752
|
-
rootCid = cid
|
|
753
|
-
try encryptAndStoreConfig()
|
|
754
|
-
if (self.fula != nil) {
|
|
755
|
-
try self.fula?.flush()
|
|
756
|
-
}
|
|
757
|
-
resolve(rootCid)
|
|
758
|
-
} else {
|
|
759
|
-
NSLog("ReactNative writeFile Error: config is nil")
|
|
760
|
-
reject("ERR_WNFS", "writeFile Error: config is nil", nil)
|
|
761
|
-
}
|
|
762
|
-
} catch let error {
|
|
763
|
-
print("writeFile", error.localizedDescription)
|
|
764
|
-
reject("ERR_WNFS", "writeFile", error)
|
|
765
|
-
}
|
|
766
|
-
}
|
|
767
|
-
|
|
768
|
-
@objc(writeFileContent:withContentString:withResolver:withRejecter:)
|
|
769
|
-
func writeFileContent(path: String, contentString: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
770
|
-
|
|
771
|
-
NSLog("ReactNative writeFile: contentString = \(contentString)")
|
|
772
|
-
NSLog("ReactNative writeFile: path = \(path)")
|
|
773
|
-
do {
|
|
774
|
-
let content = convertStringToByte(contentString)
|
|
775
|
-
let cid = try self.wnfs?.WriteFile(cid: rootCid!, remotePath: path, data: content.toData())
|
|
776
|
-
rootCid = cid
|
|
777
|
-
try encryptAndStoreConfig()
|
|
778
|
-
if (self.fula != nil) {
|
|
779
|
-
try self.fula?.flush()
|
|
780
|
-
}
|
|
781
|
-
resolve(rootCid)
|
|
782
|
-
} catch let error {
|
|
783
|
-
print("writeFileContent", error.localizedDescription)
|
|
784
|
-
reject("ERR_WNFS", "writeFileContent", error)
|
|
785
|
-
}
|
|
786
|
-
|
|
787
|
-
}
|
|
788
|
-
|
|
789
|
-
@objc(ls:withResolver:withRejecter:)
|
|
790
|
-
func ls(path: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
791
|
-
NSLog("ReactNative ls: path = \(path)")
|
|
792
|
-
do {
|
|
793
|
-
let res = try self.wnfs?.Ls(cid: rootCid!, remotePath: path)
|
|
794
|
-
|
|
795
|
-
//JSONArray jsonArray = new JSONArray(res)
|
|
796
|
-
guard let s = res?.toUTF8String() else {
|
|
797
|
-
throw MyError.runtimeError("ReactNative converting bytes to utf8 string")
|
|
798
|
-
}
|
|
799
|
-
NSLog("ReactNative ls: res = \(s)")
|
|
800
|
-
resolve(s)
|
|
801
|
-
} catch let error {
|
|
802
|
-
print("ls", error.localizedDescription)
|
|
803
|
-
reject("ERR_WNFS", "ls", error)
|
|
804
|
-
}
|
|
805
|
-
|
|
806
|
-
}
|
|
807
|
-
|
|
808
|
-
@objc(rm:withResolver:withRejecter:)
|
|
809
|
-
func rm(path: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
810
|
-
|
|
811
|
-
print("ReactNative", "rm: path = " + path)
|
|
812
|
-
do {
|
|
813
|
-
let cid = try self.wnfs?.Rm(cid: rootCid!, remotePath: path)
|
|
814
|
-
if(cid != nil) {
|
|
815
|
-
rootCid = cid
|
|
816
|
-
try encryptAndStoreConfig()
|
|
817
|
-
if (self.fula != nil) {
|
|
818
|
-
try self.fula?.flush()
|
|
819
|
-
}
|
|
820
|
-
resolve(rootCid)
|
|
821
|
-
} else {
|
|
822
|
-
print("ReactNative", "rm Error: config is nil")
|
|
823
|
-
reject("ERR_WNFS", "rm Error: config is nil", nil)
|
|
824
|
-
}
|
|
825
|
-
} catch let error {
|
|
826
|
-
print("rm", error.localizedDescription)
|
|
827
|
-
reject("ERR_WNFS", "rm", error)
|
|
828
|
-
}
|
|
829
|
-
|
|
830
|
-
}
|
|
831
|
-
|
|
832
|
-
@objc(cp:withTargetPath:withResolver:withRejecter:)
|
|
833
|
-
func cp(sourcePath: String, targetPath: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
834
|
-
|
|
835
|
-
print("ReactNative", "rm: sourcePath = " + sourcePath)
|
|
836
|
-
do {
|
|
837
|
-
let cid = try self.wnfs?.Cp(cid: rootCid!, remotePathFrom: sourcePath, remotePathTo: targetPath)
|
|
838
|
-
if(cid != nil) {
|
|
839
|
-
rootCid = cid
|
|
840
|
-
try encryptAndStoreConfig()
|
|
841
|
-
if (self.fula != nil) {
|
|
842
|
-
try self.fula?.flush()
|
|
843
|
-
}
|
|
844
|
-
resolve(rootCid)
|
|
845
|
-
} else {
|
|
846
|
-
print("ReactNative", "cp Error: config is nil")
|
|
847
|
-
reject("ERR_WNFS", "cp Error: config is nil", nil)
|
|
848
|
-
}
|
|
849
|
-
} catch let error {
|
|
850
|
-
print("cp", error.localizedDescription)
|
|
851
|
-
reject("ERR_WNFS", "cp", error)
|
|
852
|
-
}
|
|
853
|
-
|
|
854
|
-
}
|
|
855
|
-
|
|
856
|
-
@objc(mv:withTargetPath:withResolver:withRejecter:)
|
|
857
|
-
func mv(sourcePath: String, targetPath: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
858
|
-
print("ReactNative", "rm: sourcePath = " + sourcePath)
|
|
859
|
-
do {
|
|
860
|
-
let cid = try self.wnfs?.Mv(cid: rootCid!, remotePathFrom: sourcePath, remotePathTo: targetPath)
|
|
861
|
-
if(cid != nil) {
|
|
862
|
-
rootCid = cid
|
|
863
|
-
try encryptAndStoreConfig()
|
|
864
|
-
if (self.fula != nil) {
|
|
865
|
-
try self.fula?.flush()
|
|
866
|
-
}
|
|
867
|
-
resolve(rootCid)
|
|
868
|
-
} else {
|
|
869
|
-
print("ReactNative", "mv Error: config is nil")
|
|
870
|
-
reject("ERR_WNFS", "mv Error: config is nil", nil)
|
|
871
|
-
}
|
|
872
|
-
} catch let error {
|
|
873
|
-
print("mv", error.localizedDescription)
|
|
874
|
-
reject("ERR_WNFS", "mv", error)
|
|
875
|
-
}
|
|
876
|
-
|
|
877
|
-
}
|
|
878
|
-
|
|
879
|
-
@objc(readFile:withLocalFilename:withResolver:withRejecter:)
|
|
880
|
-
func readFile(fulaTargetFilename: String, localFilename: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
881
|
-
/*
|
|
882
|
-
// reads content of the file form localFilename (should include full absolute path to local file with read permission
|
|
883
|
-
// writes content to the specified location by fulaTargetFilename in Fula filesystem
|
|
884
|
-
// fulaTargetFilename: a string including full path and filename of target file on Fula (e.g. root/pictures/cat.jpg)
|
|
885
|
-
// localFilename: a string containing full path and filename of local file on hte device (e.g /usr/bin/cat.jpg)
|
|
886
|
-
// Returns: new cid of the root after this file is placed in the tree
|
|
887
|
-
*/
|
|
888
|
-
print("ReactNative", "readFile: fulaTargetFilename = " + fulaTargetFilename)
|
|
889
|
-
do {
|
|
890
|
-
let path = try self.wnfs?.ReadFileToPath(cid: rootCid!, remotePath: fulaTargetFilename, fileUrl: URL.init(string: localFilename)!)
|
|
891
|
-
resolve(path)
|
|
892
|
-
} catch let error {
|
|
893
|
-
print("readFile", error.localizedDescription)
|
|
894
|
-
reject("ERR_WNFS", "readFile", error)
|
|
895
|
-
}
|
|
896
|
-
|
|
897
|
-
}
|
|
898
|
-
|
|
899
|
-
@objc(readFileContent:withResolver:withRejecter:)
|
|
900
|
-
func readFileContent(path: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
901
|
-
|
|
902
|
-
print("ReactNative", "readFileContent: path = " + path)
|
|
903
|
-
do {
|
|
904
|
-
// FIXME: dhouldn't we output an NSData object instead?
|
|
905
|
-
let res = try self.wnfs?.ReadFile(cid: rootCid!, remotePath: path)
|
|
906
|
-
guard let resString = res?.toUTF8String() else{
|
|
907
|
-
throw MyError.runtimeError(" ReactNative converting bytes to utf8 string")
|
|
908
|
-
}
|
|
909
|
-
resolve(resString)
|
|
910
|
-
} catch let error {
|
|
911
|
-
print("readFileContent", error.localizedDescription)
|
|
912
|
-
reject("ERR_WNFS", "readFileContent", error)
|
|
913
|
-
}
|
|
914
|
-
|
|
915
|
-
}
|
|
916
|
-
|
|
917
|
-
@objc(get:withResolver:withRejecter:)
|
|
918
|
-
func get(keyString: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
919
|
-
|
|
920
|
-
print("ReactNative", "get: keyString = " + keyString)
|
|
921
|
-
do {
|
|
922
|
-
let key: Data = convertStringToByte(keyString).toData()
|
|
923
|
-
let value = try getInternal(key)
|
|
924
|
-
let valueString: String = value.toUTF8String()!
|
|
925
|
-
resolve(valueString)
|
|
926
|
-
} catch let error {
|
|
927
|
-
print("get", error.localizedDescription)
|
|
928
|
-
reject("ERR_FULA", "get", error)
|
|
929
|
-
}
|
|
930
|
-
|
|
931
|
-
}
|
|
932
|
-
|
|
933
|
-
func getInternal(_ key: Data) throws -> Data {
|
|
934
|
-
do {
|
|
935
|
-
print("ReactNative", "getInternal: key.toUTF8String() = " , key.toUTF8String()!)
|
|
936
|
-
print("ReactNative", "getInternal: key.toHex().bytes = " , key.toHex())
|
|
937
|
-
let value = try self.fula!.get(key)
|
|
938
|
-
print("ReactNative", "getInternal: value.toHex() = " , value.toHex())
|
|
939
|
-
return value
|
|
940
|
-
} catch let error {
|
|
941
|
-
print("ReactNative", "getInternal: error = " + error.localizedDescription)
|
|
942
|
-
print("getInternal", error.localizedDescription)
|
|
943
|
-
throw error
|
|
944
|
-
}
|
|
945
|
-
}
|
|
946
|
-
|
|
947
|
-
@objc(has:withResolver:withRejecter:)
|
|
948
|
-
func has(keyString: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
949
|
-
|
|
950
|
-
print("ReactNative", "has: keyString = " + keyString)
|
|
951
|
-
do {
|
|
952
|
-
let key: Data = convertStringToByte(keyString).toData()
|
|
953
|
-
let result = try hasInternal(key)
|
|
954
|
-
resolve(result)
|
|
955
|
-
} catch let error {
|
|
956
|
-
print("has", error.localizedDescription)
|
|
957
|
-
reject("ERR_FULA", "has", error)
|
|
958
|
-
}
|
|
959
|
-
|
|
960
|
-
}
|
|
961
|
-
|
|
962
|
-
func hasInternal(_ key: Data) throws -> Bool {
|
|
963
|
-
do {
|
|
964
|
-
let ret = UnsafeMutablePointer<ObjCBool>.allocate(capacity: 1)
|
|
965
|
-
try self.fula?.has(key, ret0_: ret)
|
|
966
|
-
let res = ret.pointee.boolValue
|
|
967
|
-
ret.deallocate()
|
|
968
|
-
return res
|
|
969
|
-
} catch let error {
|
|
970
|
-
print("hasInternal", error.localizedDescription)
|
|
971
|
-
throw error
|
|
972
|
-
}
|
|
973
|
-
}
|
|
974
|
-
|
|
975
|
-
func pullInternal(key: Data) throws -> Void {
|
|
976
|
-
do {
|
|
977
|
-
try self.fula!.pull(key)
|
|
978
|
-
} catch let error {
|
|
979
|
-
print("pullInternal", error.localizedDescription)
|
|
980
|
-
throw error
|
|
981
|
-
}
|
|
982
|
-
}
|
|
983
|
-
|
|
984
|
-
@objc(push:withRejecter:)
|
|
985
|
-
func push(resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
986
|
-
print("ReactNative", "push started")
|
|
987
|
-
do {
|
|
988
|
-
try pushInternal(key: convertStringToByte(rootCid!).toData())
|
|
989
|
-
resolve(rootCid)
|
|
990
|
-
} catch let error {
|
|
991
|
-
print("get", error.localizedDescription)
|
|
992
|
-
reject("ERR_FULA", "push", error)
|
|
993
|
-
}
|
|
994
|
-
}
|
|
995
|
-
|
|
996
|
-
func pushInternal(key: Data) throws -> Void {
|
|
997
|
-
do {
|
|
998
|
-
let hasIt = try hasInternal(key)
|
|
999
|
-
if (self.fula != nil && hasIt) {
|
|
1000
|
-
try self.fula?.push(key)
|
|
1001
|
-
try self.fula?.flush()
|
|
1002
|
-
} else {
|
|
1003
|
-
print("ReactNative", "pushInternal error: key wasn't found or fula is not initialized")
|
|
1004
|
-
throw MyError.runtimeError("ReactNative pushInternal error: key wasn't found or fula is not initialized")
|
|
1005
|
-
}
|
|
1006
|
-
} catch let error {
|
|
1007
|
-
print("ReactNative", "pushInternal", error.localizedDescription)
|
|
1008
|
-
throw error
|
|
1009
|
-
}
|
|
1010
|
-
}
|
|
1011
|
-
|
|
1012
|
-
// FIXME: unused codecString arg
|
|
1013
|
-
@objc(put:withCodecString:withResolver:withRejecter:)
|
|
1014
|
-
func put(valueString: String, codecString: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
1015
|
-
|
|
1016
|
-
print("ReactNative", "put: codecString = " + codecString)
|
|
1017
|
-
print("ReactNative", "put: valueString = " + valueString)
|
|
1018
|
-
do {
|
|
1019
|
-
//byte[] codec = convertStringToByte(CodecString)
|
|
1020
|
-
let codec = FulaModule.CODEC_DAG_CBOR
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
print("ReactNative", "put: codec = ", codec)
|
|
1024
|
-
let value = valueString.toData()
|
|
1025
|
-
|
|
1026
|
-
print("ReactNative", "put: value.toHex() = " , value.toHex())
|
|
1027
|
-
let key = try putInternal(value: value, codec: codec)
|
|
1028
|
-
print("ReactNative", "put: key.toHex() = " , key.toUTF8String()!)
|
|
1029
|
-
resolve(key.toUTF8String()!)
|
|
1030
|
-
} catch let error {
|
|
1031
|
-
print("ReactNative", "put: error = ", error.localizedDescription)
|
|
1032
|
-
reject("ERR_FULA", "put", error)
|
|
1033
|
-
}
|
|
1034
|
-
|
|
1035
|
-
}
|
|
1036
|
-
|
|
1037
|
-
// FIXME: unused codec arg
|
|
1038
|
-
func putInternal(value: Data, codec: Int) throws -> Data {
|
|
1039
|
-
do {
|
|
1040
|
-
if(self.fula != nil) {
|
|
1041
|
-
let key: Data = try self.fula!.put(value, codec: Int64(FulaModule.CODEC_DAG_CBOR))
|
|
1042
|
-
try self.fula?.flush()
|
|
1043
|
-
return key
|
|
1044
|
-
} else {
|
|
1045
|
-
print("ReactNative", "putInternal Error: fula is not initialized")
|
|
1046
|
-
throw MyError.runtimeError("ReactNative putInternal Error: fula is not initialized")
|
|
1047
|
-
}
|
|
1048
|
-
} catch let error {
|
|
1049
|
-
print("ReactNative", "putInternal", error.localizedDescription)
|
|
1050
|
-
throw error
|
|
1051
|
-
}
|
|
1052
|
-
}
|
|
1053
|
-
|
|
1054
|
-
@objc(setAuth:withAllow:withResolver:withRejecter:)
|
|
1055
|
-
func setAuth(peerIdString: String, allow: Bool, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
1056
|
-
|
|
1057
|
-
print("ReactNative", "setAuth: peerIdString = " + peerIdString)
|
|
1058
|
-
do {
|
|
1059
|
-
if (self.fula != nil && !(self.fula?.id_().isEmpty)! && fulaConfig != nil && !fulaConfig!.bloxAddr.isEmpty) {
|
|
1060
|
-
let bloxAddr = fulaConfig!.bloxAddr
|
|
1061
|
-
print("ReactNative", "setAuth: bloxAddr = '",bloxAddr,"'"," peerIdString = '",peerIdString,"'")
|
|
1062
|
-
let parts = bloxAddr.split(separator: "/").map(String.init)
|
|
1063
|
-
try self.fula?.setAuth(parts.last, subject: peerIdString, allow: allow)
|
|
1064
|
-
resolve(true)
|
|
1065
|
-
} else {
|
|
1066
|
-
print("ReactNative", "setAuth error: fula is not initialized")
|
|
1067
|
-
throw MyError.runtimeError("ReactNative fula is not initialized")
|
|
1068
|
-
}
|
|
1069
|
-
resolve(false)
|
|
1070
|
-
} catch let error {
|
|
1071
|
-
print("get", error.localizedDescription)
|
|
1072
|
-
reject("ERR_FULA", "setAuth", error)
|
|
1073
|
-
}
|
|
1074
|
-
|
|
1075
|
-
}
|
|
1076
|
-
|
|
1077
|
-
@objc(clearCidsFromRecent:withResolver:withRejecter:)
|
|
1078
|
-
func clearCidsFromRecent(cidArray: NSArray, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1079
|
-
DispatchQueue.global(qos: .default).async {
|
|
1080
|
-
do {
|
|
1081
|
-
guard let fulaClient = self.fula else {
|
|
1082
|
-
throw MyError.runtimeError("ReactNative Fula client is not initialized")
|
|
1083
|
-
}
|
|
1084
|
-
|
|
1085
|
-
// Concatenate all CID strings into a single string separated by "|"
|
|
1086
|
-
let concatenatedCids = (cidArray as? [String])?.joined(separator: "|")
|
|
1087
|
-
|
|
1088
|
-
guard let cidsData = concatenatedCids?.data(using: .utf8) else {
|
|
1089
|
-
throw MyError.runtimeError("ReactNative Unable to encode CIDs as data")
|
|
1090
|
-
}
|
|
1091
|
-
|
|
1092
|
-
try fulaClient.clearCids(fromRecent: cidsData)
|
|
1093
|
-
resolve(true)
|
|
1094
|
-
} catch let error {
|
|
1095
|
-
print("ReactNative", "clearCidsFromRecent failed with Error: \(error.localizedDescription)")
|
|
1096
|
-
reject("ERR_FULA_CLEAR_CIDS", "Failed to clear CIDs from recent", error)
|
|
1097
|
-
}
|
|
1098
|
-
}
|
|
1099
|
-
}
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
@objc(listRecentCidsAsString:withRejecter:)
|
|
1103
|
-
func listRecentCidsAsString(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1104
|
-
DispatchQueue.global(qos: .default).async {
|
|
1105
|
-
do {
|
|
1106
|
-
guard let fulaClient = self.fula else {
|
|
1107
|
-
throw MyError.runtimeError("ReactNative Fula client is not initialized")
|
|
1108
|
-
}
|
|
1109
|
-
|
|
1110
|
-
let recentLinksIterator = try fulaClient.listRecentCidsAsString()
|
|
1111
|
-
var recentLinksList = [String]()
|
|
1112
|
-
|
|
1113
|
-
while recentLinksIterator.hasNext() {
|
|
1114
|
-
var error: NSError?
|
|
1115
|
-
let nextLink = try recentLinksIterator.next(&error)
|
|
1116
|
-
|
|
1117
|
-
if let error = error {
|
|
1118
|
-
throw error
|
|
1119
|
-
}
|
|
1120
|
-
|
|
1121
|
-
recentLinksList.append(nextLink)
|
|
1122
|
-
}
|
|
1123
|
-
|
|
1124
|
-
if !recentLinksList.isEmpty {
|
|
1125
|
-
// Return the whole list
|
|
1126
|
-
resolve(recentLinksList)
|
|
1127
|
-
} else {
|
|
1128
|
-
resolve(false)
|
|
1129
|
-
}
|
|
1130
|
-
} catch let error {
|
|
1131
|
-
print("ReactNative", "listRecentCidsAsString failed with Error: \(error.localizedDescription)")
|
|
1132
|
-
reject("ERR_FULA_LIST_RECENT_CIDS", "Failed to list recent CIDs as string", error)
|
|
1133
|
-
}
|
|
1134
|
-
}
|
|
1135
|
-
}
|
|
1136
|
-
|
|
1137
|
-
@objc(listRecentCidsAsStringWithChildren:withRejecter:)
|
|
1138
|
-
func listRecentCidsAsStringWithChildren(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1139
|
-
DispatchQueue.global(qos: .default).async {
|
|
1140
|
-
do {
|
|
1141
|
-
guard let fulaClient = self.fula else {
|
|
1142
|
-
throw MyError.runtimeError("ReactNative Fula client is not initialized")
|
|
1143
|
-
}
|
|
1144
|
-
|
|
1145
|
-
let recentLinksIterator = try fulaClient.listRecentCidsAsStringWithChildren()
|
|
1146
|
-
var recentLinksList = [String]()
|
|
1147
|
-
|
|
1148
|
-
while recentLinksIterator.hasNext() {
|
|
1149
|
-
var error: NSError?
|
|
1150
|
-
let nextLink = try recentLinksIterator.next(&error)
|
|
1151
|
-
|
|
1152
|
-
if let error = error {
|
|
1153
|
-
throw error
|
|
1154
|
-
}
|
|
1155
|
-
|
|
1156
|
-
recentLinksList.append(nextLink)
|
|
1157
|
-
}
|
|
1158
|
-
|
|
1159
|
-
if !recentLinksList.isEmpty {
|
|
1160
|
-
// Return the whole list
|
|
1161
|
-
resolve(recentLinksList)
|
|
1162
|
-
} else {
|
|
1163
|
-
resolve(false)
|
|
1164
|
-
}
|
|
1165
|
-
} catch let error {
|
|
1166
|
-
print("ReactNative", "listRecentCidsAsStringWithChildren failed with Error: \(error.localizedDescription)")
|
|
1167
|
-
reject("ERR_FULA_LIST_RECENT_CIDS_WITH_CHILDREN", "Failed to list recent CIDs as string with children", error)
|
|
1168
|
-
}
|
|
1169
|
-
}
|
|
1170
|
-
}
|
|
1171
|
-
|
|
1172
|
-
@objc(batchUploadManifest:withPoolId:withReplicationFactor:withResolver:withRejecter:)
|
|
1173
|
-
func batchUploadManifest(cidArray: NSArray, poolIDStr: String, replicationFactorStr: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1174
|
-
DispatchQueue.global(qos: .default).async {
|
|
1175
|
-
do {
|
|
1176
|
-
guard let fulaClient = self.fula else {
|
|
1177
|
-
throw MyError.runtimeError("ReactNative Fula client is not initialized")
|
|
1178
|
-
}
|
|
1179
|
-
guard let poolID = Int64(poolIDStr) else {
|
|
1180
|
-
let error = NSError(domain: "FULAErrorDomain", code: 1001, userInfo: [NSLocalizedDescriptionKey: "Invalid poolID - not a valid number: \(poolIDStr)"])
|
|
1181
|
-
reject("ERR_FULA", "Invalid poolID - not a valid number: \(poolIDStr)", error)
|
|
1182
|
-
return
|
|
1183
|
-
}
|
|
1184
|
-
guard let replicationFactor = Int64(replicationFactorStr) else {
|
|
1185
|
-
let error = NSError(domain: "FULAErrorDomain",
|
|
1186
|
-
code: 1002,
|
|
1187
|
-
userInfo: [NSLocalizedDescriptionKey: "Invalid replicationFactor - not a valid number: \(replicationFactorStr)"])
|
|
1188
|
-
reject("ERR_FULA", "Invalid replicationFactorStr - not a valid number: \(replicationFactorStr)", error)
|
|
1189
|
-
return
|
|
1190
|
-
}
|
|
1191
|
-
|
|
1192
|
-
// Concatenate all CID strings into a single string separated by "|"
|
|
1193
|
-
let concatenatedCids = (cidArray as? [String])?.joined(separator: "|")
|
|
1194
|
-
|
|
1195
|
-
guard let cidsData = concatenatedCids?.data(using: .utf8) else {
|
|
1196
|
-
throw MyError.runtimeError("ReactNative Unable to encode CIDs as data")
|
|
1197
|
-
}
|
|
1198
|
-
|
|
1199
|
-
// Adjusted call to match the expected method signature and argument types
|
|
1200
|
-
try fulaClient.batchUploadManifest(cidsData, poolID: Int(poolID), replicationFactor: Int(replicationFactor))
|
|
1201
|
-
resolve(true)
|
|
1202
|
-
} catch let error {
|
|
1203
|
-
print("ReactNative", "batchUploadManifest failed with Error: \(error.localizedDescription)")
|
|
1204
|
-
reject("ERR_FULA_BATCH_UPLOAD_MANIFEST", "Failed to batch upload CIDs", error)
|
|
1205
|
-
}
|
|
1206
|
-
}
|
|
1207
|
-
}
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
@objc(shutdown:withRejecter:)
|
|
1212
|
-
func shutdown( resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) {
|
|
1213
|
-
do {
|
|
1214
|
-
try shutdownInternal()
|
|
1215
|
-
resolve(true)
|
|
1216
|
-
} catch let error {
|
|
1217
|
-
NSLog("ReactNative shutdown \(error.localizedDescription)")
|
|
1218
|
-
reject("ERR_FULA", "shutdown", error)
|
|
1219
|
-
}
|
|
1220
|
-
|
|
1221
|
-
}
|
|
1222
|
-
|
|
1223
|
-
@objc
|
|
1224
|
-
func deleteDsLock(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1225
|
-
let lockFilePath = (fulaConfig!.storePath as NSString).appendingPathComponent("LOCK")
|
|
1226
|
-
let fileManager = FileManager.default
|
|
1227
|
-
|
|
1228
|
-
do {
|
|
1229
|
-
if fileManager.fileExists(atPath: lockFilePath) {
|
|
1230
|
-
try fileManager.removeItem(atPath: lockFilePath)
|
|
1231
|
-
NSLog("ReactNative: Lock file deleted successfully.")
|
|
1232
|
-
resolve(true)
|
|
1233
|
-
} else {
|
|
1234
|
-
NSLog("ReactNative: Lock file does not exist.")
|
|
1235
|
-
resolve(false) // Resolve with false if the file doesn't exist
|
|
1236
|
-
}
|
|
1237
|
-
} catch let error as NSError {
|
|
1238
|
-
NSLog("ReactNative: Failed to delete lock file: \(error.localizedDescription)")
|
|
1239
|
-
reject("delete_error", "Failed to delete lock file", error)
|
|
1240
|
-
}
|
|
1241
|
-
}
|
|
1242
|
-
|
|
1243
|
-
func shutdownInternal() {
|
|
1244
|
-
NSLog("ReactNative shutdownInternal")
|
|
1245
|
-
if self.fula != nil {
|
|
1246
|
-
NSLog("ReactNative shutdownInternal fula is not null")
|
|
1247
|
-
do {
|
|
1248
|
-
try self.fula?.shutdown()
|
|
1249
|
-
NSLog("ReactNative shutdownInternal fula.shutdown called")
|
|
1250
|
-
} catch {
|
|
1251
|
-
// Handle specific errors if needed or log them
|
|
1252
|
-
NSLog("ReactNative shutdownInternal error: \(error.localizedDescription)")
|
|
1253
|
-
}
|
|
1254
|
-
// Ensure resources are cleaned up regardless of errors
|
|
1255
|
-
self.fula = nil
|
|
1256
|
-
self.client = nil
|
|
1257
|
-
self.wnfs = nil
|
|
1258
|
-
}
|
|
1259
|
-
}
|
|
1260
|
-
|
|
1261
|
-
///////////////////////////////////////////////////////////
|
|
1262
|
-
///////////////////////////////////////////////////////////
|
|
1263
|
-
///////////////////////////////////////////////////////////
|
|
1264
|
-
///////////////////////////////////////////////////////////
|
|
1265
|
-
//////////////////////ANYTHING BELOW IS FOR BLOCKCHAIN/////
|
|
1266
|
-
///////////////////////////////////////////////////////////
|
|
1267
|
-
|
|
1268
|
-
@objc(checkAccountExists:withResolver:withRejecter:)
|
|
1269
|
-
func checkAccountExists(accountString: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
1270
|
-
print("ReactNative", "checkAccountExists: accountString = ", accountString)
|
|
1271
|
-
do {
|
|
1272
|
-
let result = try self.fula!.accountExists(accountString)
|
|
1273
|
-
let resultString = result.toUTF8String()!
|
|
1274
|
-
resolve(resultString)
|
|
1275
|
-
} catch let error {
|
|
1276
|
-
print("checkAccountExists", error.localizedDescription)
|
|
1277
|
-
reject("ERR_FULA", "checkAccountExists", error)
|
|
1278
|
-
}
|
|
1279
|
-
|
|
1280
|
-
}
|
|
1281
|
-
|
|
1282
|
-
@objc(accountFund:withResolver:withRejecter:)
|
|
1283
|
-
func accountFund(accountString: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
1284
|
-
print("ReactNative", "accountFund: accountString = ", accountString)
|
|
1285
|
-
do {
|
|
1286
|
-
let result = try self.fula!.accountFund(accountString)
|
|
1287
|
-
let resultString = result.toUTF8String()!
|
|
1288
|
-
resolve(resultString)
|
|
1289
|
-
} catch let error {
|
|
1290
|
-
print("accountFund", error.localizedDescription)
|
|
1291
|
-
reject("ERR_FULA", "accountFund", error)
|
|
1292
|
-
}
|
|
1293
|
-
|
|
1294
|
-
}
|
|
1295
|
-
|
|
1296
|
-
@objc(listPools:withRejecter:)
|
|
1297
|
-
func listPools( resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
1298
|
-
print("ReactNative", "listPools")
|
|
1299
|
-
do {
|
|
1300
|
-
let result = try self.fula!.poolList()
|
|
1301
|
-
let resultString = result.toUTF8String()!
|
|
1302
|
-
resolve(resultString)
|
|
1303
|
-
} catch let error {
|
|
1304
|
-
print("listPools", error.localizedDescription)
|
|
1305
|
-
reject("ERR_FULA", "listPools", error)
|
|
1306
|
-
}
|
|
1307
|
-
|
|
1308
|
-
}
|
|
1309
|
-
|
|
1310
|
-
@objc(listPoolJoinRequests:withResolver:withRejecter:)
|
|
1311
|
-
func listPoolJoinRequests(poolIDStr: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1312
|
-
print("ReactNative", "listPoolJoinRequests: poolIDStr = ", poolIDStr)
|
|
1313
|
-
do {
|
|
1314
|
-
if let poolID = Int64(poolIDStr), let intPoolID = Int(exactly: poolID) {
|
|
1315
|
-
// Conversion to Int successful - use intPoolID
|
|
1316
|
-
let result = try self.fula!.poolRequests(intPoolID)
|
|
1317
|
-
let resultString = result.toUTF8String()!
|
|
1318
|
-
resolve(resultString)
|
|
1319
|
-
} else {
|
|
1320
|
-
// Handle invalid input or Int64 not convertible to Int
|
|
1321
|
-
let error = NSError(domain: "FULAErrorDomain",
|
|
1322
|
-
code: 1003,
|
|
1323
|
-
userInfo: [NSLocalizedDescriptionKey: "Invalid poolIDStr - not a valid number or too large: \(poolIDStr)"])
|
|
1324
|
-
reject("ERR_FULA", "Invalid poolIDStr - not a valid number or too large: \(poolIDStr)", error)
|
|
1325
|
-
}
|
|
1326
|
-
} catch let error {
|
|
1327
|
-
print("listPoolJoinRequests", error.localizedDescription)
|
|
1328
|
-
let nsError = error as NSError
|
|
1329
|
-
reject("ERR_FULA", "Failed listPoolJoinRequests due to error", nsError)
|
|
1330
|
-
}
|
|
1331
|
-
}
|
|
1332
|
-
|
|
1333
|
-
@objc(listAvailableReplicationRequests:withResolver:withRejecter:)
|
|
1334
|
-
func listAvailableReplicationRequests(poolIDStr: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1335
|
-
print("ReactNative", "listAvailableReplicationRequests: poolIDStr = ", poolIDStr)
|
|
1336
|
-
do {
|
|
1337
|
-
guard let poolID = Int64(poolIDStr), let intPoolID = Int(exactly: poolID) else {
|
|
1338
|
-
let error = NSError(domain: "FULAErrorDomain",
|
|
1339
|
-
code: 1004, // Use appropriate error code
|
|
1340
|
-
userInfo: [NSLocalizedDescriptionKey: "Invalid poolID - not a valid number: \(poolIDStr)"])
|
|
1341
|
-
reject("ERR_FULA", "Invalid poolID - not a valid number: \(poolIDStr)", error)
|
|
1342
|
-
return
|
|
1343
|
-
}
|
|
1344
|
-
let result = try self.fula!.manifestAvailable(intPoolID)
|
|
1345
|
-
guard let resultString = result.toUTF8String() else {
|
|
1346
|
-
let error = NSError(domain: "FULAErrorDomain",
|
|
1347
|
-
code: 1005, // Use appropriate error code
|
|
1348
|
-
userInfo: [NSLocalizedDescriptionKey: "Failed to convert result to UTF8 String"])
|
|
1349
|
-
reject("ERR_FULA", "Conversion Error", error)
|
|
1350
|
-
return
|
|
1351
|
-
}
|
|
1352
|
-
resolve(resultString)
|
|
1353
|
-
} catch let error as NSError {
|
|
1354
|
-
print("listAvailableReplicationRequests", error.localizedDescription)
|
|
1355
|
-
reject("ERR_FULA", "listAvailableReplicationRequests failed with error: \(error.localizedDescription)", error)
|
|
1356
|
-
}
|
|
1357
|
-
}
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
@objc(bloxFreeSpace:withRejecter:)
|
|
1361
|
-
func bloxFreeSpace(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
|
|
1362
|
-
print("ReactNative", "bloxFreeSpace")
|
|
1363
|
-
guard let fulaClient = self.fula else {
|
|
1364
|
-
print("bloxFreeSpace", "fula client is nil")
|
|
1365
|
-
let error = NSError(domain: "FulaModuleError", code: 0, userInfo: [NSLocalizedDescriptionKey: "Fula client is not initialized"])
|
|
1366
|
-
reject("ERR_FULA_NOT_INITIALIZED", "Fula client is not initialized", error)
|
|
1367
|
-
return
|
|
1368
|
-
}
|
|
1369
|
-
|
|
1370
|
-
do {
|
|
1371
|
-
let result = try fulaClient.bloxFreeSpace()
|
|
1372
|
-
guard let resultString = result.toUTF8String() else {
|
|
1373
|
-
let error = NSError(domain: "FulaModuleError", code: 1, userInfo: [NSLocalizedDescriptionKey: "Failed to convert result to String"])
|
|
1374
|
-
reject("ERR_FULA_RESULT_CONVERSION", "Failed to convert result to String", error)
|
|
1375
|
-
return
|
|
1376
|
-
}
|
|
1377
|
-
resolve(resultString)
|
|
1378
|
-
} catch let error {
|
|
1379
|
-
print("bloxFreeSpace", error.localizedDescription)
|
|
1380
|
-
reject("ERR_FULA", "bloxFreeSpace", error)
|
|
1381
|
-
}
|
|
1382
|
-
}
|
|
1383
|
-
|
|
1384
|
-
@objc(transferToFula:wallet:chain:withResolver:withRejecter:)
|
|
1385
|
-
func transferToFula(amount: String, wallet: String, chain: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1386
|
-
DispatchQueue.global(qos: .default).async {
|
|
1387
|
-
do {
|
|
1388
|
-
print("ReactNative", "transferToFula called")
|
|
1389
|
-
let result = try self.fula!.transfer(toFula: amount, walletAccount: wallet, chain: chain)
|
|
1390
|
-
let resultString = String(data: result, encoding: .utf8)
|
|
1391
|
-
resolve(resultString)
|
|
1392
|
-
} catch let error {
|
|
1393
|
-
print("ReactNative", "transferToFula failed with Error: \(error.localizedDescription)")
|
|
1394
|
-
reject("ERR_FULA_TRANSFER", "transferToFula failed", error)
|
|
1395
|
-
}
|
|
1396
|
-
}
|
|
1397
|
-
}
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
@objc(getAccount:withRejecter:)
|
|
1401
|
-
func getAccount(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1402
|
-
guard let fulaClient = self.fula else {
|
|
1403
|
-
let error = NSError(domain: "FulaModuleError", code: -1, userInfo: [NSLocalizedDescriptionKey: "Fula client is not initialized"])
|
|
1404
|
-
reject("ERR_FULA_NOT_INITIALIZED", "Fula client is not initialized", error)
|
|
1405
|
-
return
|
|
1406
|
-
}
|
|
1407
|
-
|
|
1408
|
-
do {
|
|
1409
|
-
let account = try fulaClient.getAccount()
|
|
1410
|
-
guard let accountString = String(data: account, encoding: .utf8) else {
|
|
1411
|
-
let conversionError = NSError(domain: "FulaModuleError", code: -2, userInfo: [NSLocalizedDescriptionKey: "Unable to convert account data to String"])
|
|
1412
|
-
reject("ERR_FULA_CONVERSION_FAILED", "Unable to convert account data to String", conversionError)
|
|
1413
|
-
return
|
|
1414
|
-
}
|
|
1415
|
-
resolve(accountString)
|
|
1416
|
-
} catch let error {
|
|
1417
|
-
reject("ERR_FULA", "getAccount: \(error.localizedDescription)", error)
|
|
1418
|
-
}
|
|
1419
|
-
}
|
|
1420
|
-
|
|
1421
|
-
@objc(assetsBalance:withAssetId:withClassId:withResolver:withRejecter:)
|
|
1422
|
-
func assetsBalance(account: String, assetId: String, classId: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1423
|
-
guard let assetIdInt = Int(assetId), let classIdInt = Int(classId) else {
|
|
1424
|
-
reject("ERR_FULA", "Invalid assetId or classId", nil)
|
|
1425
|
-
return
|
|
1426
|
-
}
|
|
1427
|
-
|
|
1428
|
-
do {
|
|
1429
|
-
let balance = try self.fula!.assetsBalance(account, assetId: assetIdInt, classId: classIdInt)
|
|
1430
|
-
let balanceString = String(data: balance, encoding: .utf8)
|
|
1431
|
-
resolve(balanceString)
|
|
1432
|
-
} catch let error {
|
|
1433
|
-
reject("ERR_FULA", "assetsBalance: \(error.localizedDescription)", error)
|
|
1434
|
-
}
|
|
1435
|
-
}
|
|
1436
|
-
|
|
1437
|
-
@objc(joinPool:withResolver:withRejecter:)
|
|
1438
|
-
func joinPool(poolID: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1439
|
-
print("ReactNative", "joinPool: poolID = ", poolID)
|
|
1440
|
-
do {
|
|
1441
|
-
guard let poolIdInt = Int(poolID) else {
|
|
1442
|
-
throw NSError(domain: "Invalid poolID", code: 0, userInfo: nil)
|
|
1443
|
-
}
|
|
1444
|
-
let result = try self.fula!.poolJoin(poolIdInt)
|
|
1445
|
-
let resultString = String(data: result, encoding: .utf8)
|
|
1446
|
-
resolve(resultString)
|
|
1447
|
-
} catch let error {
|
|
1448
|
-
reject("ERR_FULA", "joinPool: \(error.localizedDescription)", error)
|
|
1449
|
-
}
|
|
1450
|
-
}
|
|
1451
|
-
|
|
1452
|
-
@objc(cancelPoolJoin:withResolver:withRejecter:)
|
|
1453
|
-
func cancelPoolJoin(poolID: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1454
|
-
do {
|
|
1455
|
-
guard let poolIdInt = Int(poolID) else {
|
|
1456
|
-
throw NSError(domain: "Invalid poolID", code: 0, userInfo: nil)
|
|
1457
|
-
}
|
|
1458
|
-
let result = try self.fula!.poolCancelJoin(poolIdInt)
|
|
1459
|
-
let resultString = String(data: result, encoding: .utf8)
|
|
1460
|
-
resolve(resultString)
|
|
1461
|
-
} catch let error {
|
|
1462
|
-
reject("ERR_FULA", "cancelPoolJoin: \(error.localizedDescription)", error)
|
|
1463
|
-
}
|
|
1464
|
-
}
|
|
1465
|
-
|
|
1466
|
-
@objc(leavePool:withResolver:withRejecter:)
|
|
1467
|
-
func leavePool(poolID: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1468
|
-
print("ReactNative", "leavePool: poolID = ", poolID)
|
|
1469
|
-
do {
|
|
1470
|
-
guard let poolIdInt = Int(poolID) else {
|
|
1471
|
-
throw NSError(domain: "Invalid poolID", code: 0, userInfo: nil)
|
|
1472
|
-
}
|
|
1473
|
-
let result = try self.fula!.poolLeave(poolIdInt)
|
|
1474
|
-
let resultString = String(data: result, encoding: .utf8)
|
|
1475
|
-
resolve(resultString)
|
|
1476
|
-
} catch let error {
|
|
1477
|
-
reject("ERR_FULA", "leavePool: \(error.localizedDescription)", error)
|
|
1478
|
-
}
|
|
1479
|
-
}
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
@objc(eraseBlData:withRejecter:)
|
|
1483
|
-
func eraseBlData(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1484
|
-
do {
|
|
1485
|
-
let result = try self.fula!.eraseBlData()
|
|
1486
|
-
let resultString = String(data: result, encoding: .utf8)
|
|
1487
|
-
resolve(resultString)
|
|
1488
|
-
} catch let error {
|
|
1489
|
-
reject("ERR_FULA", "eraseBlData: \(error.localizedDescription)", error)
|
|
1490
|
-
}
|
|
1491
|
-
}
|
|
1492
|
-
|
|
1493
|
-
@objc(reboot:withRejecter:)
|
|
1494
|
-
func reboot(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
|
|
1495
|
-
do {
|
|
1496
|
-
let result = try self.fula!.reboot()
|
|
1497
|
-
let resultString = result.toUTF8String()!
|
|
1498
|
-
resolve(resultString)
|
|
1499
|
-
} catch let error {
|
|
1500
|
-
print("reboot", error.localizedDescription)
|
|
1501
|
-
reject("ERR_FULA", "reboot", error)
|
|
1502
|
-
}
|
|
1503
|
-
}
|
|
1504
|
-
|
|
1505
|
-
@objc(partition:withRejecter:)
|
|
1506
|
-
func partition(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
|
|
1507
|
-
do {
|
|
1508
|
-
let result = try self.fula!.partition()
|
|
1509
|
-
let resultString = result.toUTF8String()!
|
|
1510
|
-
resolve(resultString)
|
|
1511
|
-
} catch let error {
|
|
1512
|
-
print("partition", error.localizedDescription)
|
|
1513
|
-
reject("ERR_FULA", "partition", error)
|
|
1514
|
-
}
|
|
1515
|
-
}
|
|
1516
|
-
|
|
1517
|
-
@objc(wifiRemoveall:withRejecter:)
|
|
1518
|
-
func wifiRemoveall(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
|
|
1519
|
-
do {
|
|
1520
|
-
let result = try self.fula!.wifiRemoveall()
|
|
1521
|
-
let resultString = result.toUTF8String()!
|
|
1522
|
-
resolve(resultString)
|
|
1523
|
-
} catch let error {
|
|
1524
|
-
print("wifiRemoveall", error.localizedDescription)
|
|
1525
|
-
reject("ERR_FULA", "wifiRemoveall", error)
|
|
1526
|
-
}
|
|
1527
|
-
}
|
|
1528
|
-
|
|
1529
|
-
@objc(fetchContainerLogs:withTailCount:withResolver:withRejecter:)
|
|
1530
|
-
func fetchContainerLogs(containerName: String, tailCount: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1531
|
-
do {
|
|
1532
|
-
// Since fetchContainerLogs expects a String for tailCount, pass it directly
|
|
1533
|
-
let result = try self.fula!.fetchContainerLogs(containerName, tailCount: tailCount)
|
|
1534
|
-
guard let resultString = result.toUTF8String() else {
|
|
1535
|
-
// Handle the case where result.toUTF8String() returns nil
|
|
1536
|
-
let error = NSError(domain: "FULAErrorDomain",
|
|
1537
|
-
code: 1007, // Choose a suitable error code
|
|
1538
|
-
userInfo: [NSLocalizedDescriptionKey: "Failed to convert log data to string."])
|
|
1539
|
-
reject("ERR_FULA", "Log Conversion Error", error)
|
|
1540
|
-
return
|
|
1541
|
-
}
|
|
1542
|
-
resolve(resultString)
|
|
1543
|
-
} catch let error as NSError {
|
|
1544
|
-
print("fetchContainerLogs", error.localizedDescription)
|
|
1545
|
-
reject("ERR_FULA", "fetchContainerLogs failed", error)
|
|
1546
|
-
}
|
|
1547
|
-
}
|
|
1548
|
-
@objc(findBestAndTargetInLogs:withTailCount:withResolver:withRejecter:)
|
|
1549
|
-
func findBestAndTargetInLogs(containerName: String, tailCount: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1550
|
-
do {
|
|
1551
|
-
// Since fetchContainerLogs expects a String for tailCount, pass it directly
|
|
1552
|
-
let result = try self.fula!.findBestAndTarget(inLogs: containerName, tailCount: tailCount)
|
|
1553
|
-
guard let resultString = result.toUTF8String() else {
|
|
1554
|
-
// Handle the case where result.toUTF8String() returns nil
|
|
1555
|
-
let error = NSError(domain: "FULAErrorDomain",
|
|
1556
|
-
code: 1007, // Choose a suitable error code
|
|
1557
|
-
userInfo: [NSLocalizedDescriptionKey: "Failed to convert log data to string."])
|
|
1558
|
-
reject("ERR_FULA", "Log Conversion Error", error)
|
|
1559
|
-
return
|
|
1560
|
-
}
|
|
1561
|
-
resolve(resultString)
|
|
1562
|
-
} catch let error as NSError {
|
|
1563
|
-
print("fetchContainerLogs", error.localizedDescription)
|
|
1564
|
-
reject("ERR_FULA", "fetchContainerLogs failed", error)
|
|
1565
|
-
}
|
|
1566
|
-
}
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
@objc(getFolderSize:withResolver:withRejecter:)
|
|
1571
|
-
func getFolderSize(folderPath: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
|
|
1572
|
-
// Validate the folder path
|
|
1573
|
-
guard !folderPath.isEmpty else {
|
|
1574
|
-
reject("ERR_INVALID_PATH", "The folder path is empty.", nil)
|
|
1575
|
-
return
|
|
1576
|
-
}
|
|
1577
|
-
|
|
1578
|
-
do {
|
|
1579
|
-
// Ensure fula is not nil before calling getFolderSize
|
|
1580
|
-
guard let fula = self.fula else {
|
|
1581
|
-
reject("ERR_FULA", "Fula instance is not initialized.", nil)
|
|
1582
|
-
return
|
|
1583
|
-
}
|
|
1584
|
-
|
|
1585
|
-
// Attempt to get the folder size
|
|
1586
|
-
let result = try fula.getFolderSize(folderPath)
|
|
1587
|
-
|
|
1588
|
-
// Convert the result to a UTF-8 string safely
|
|
1589
|
-
if let resultString = result.toUTF8String() {
|
|
1590
|
-
resolve(resultString)
|
|
1591
|
-
} else {
|
|
1592
|
-
reject("ERR_CONVERSION", "Failed to convert result to UTF-8 string.", nil)
|
|
1593
|
-
}
|
|
1594
|
-
} catch let error {
|
|
1595
|
-
// Log and reject with detailed error information
|
|
1596
|
-
print("getFolderSize error:", error.localizedDescription)
|
|
1597
|
-
reject("ERR_FULA", "Failed to get folder size: \(error.localizedDescription)", error)
|
|
1598
|
-
}
|
|
1599
|
-
}
|
|
1600
|
-
|
|
1601
|
-
@objc
|
|
1602
|
-
func getDatastoreSize(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
|
|
1603
|
-
DispatchQueue.global(qos: .background).async {
|
|
1604
|
-
// Safely unwrap `self.fula` using `guard let`
|
|
1605
|
-
guard let fulaClient = self.fula else {
|
|
1606
|
-
let error = NSError(domain: "FulaModuleError", code: 0, userInfo: [NSLocalizedDescriptionKey: "Fula client is not initialized"])
|
|
1607
|
-
DispatchQueue.main.async {
|
|
1608
|
-
reject("ERR_FULA_NOT_INITIALIZED", "Fula client is not initialized", error)
|
|
1609
|
-
}
|
|
1610
|
-
return
|
|
1611
|
-
}
|
|
1612
|
-
|
|
1613
|
-
do {
|
|
1614
|
-
let result = try fulaClient.getDatastoreSize()
|
|
1615
|
-
let resultString = String(decoding: result, as: UTF8.self)
|
|
1616
|
-
DispatchQueue.main.async {
|
|
1617
|
-
resolve(resultString)
|
|
1618
|
-
}
|
|
1619
|
-
} catch let error {
|
|
1620
|
-
DispatchQueue.main.async {
|
|
1621
|
-
reject("ERR_FULA", "Failed to get datastore size: \(error.localizedDescription)", error)
|
|
1622
|
-
}
|
|
1623
|
-
}
|
|
1624
|
-
}
|
|
1625
|
-
}
|
|
1626
|
-
|
|
1627
|
-
@objc(listPlugins:withRejecter:)
|
|
1628
|
-
func listPlugins(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1629
|
-
DispatchQueue.global(qos: .background).async {
|
|
1630
|
-
do {
|
|
1631
|
-
guard let fula = self.fula else {
|
|
1632
|
-
let error = NSError(domain: "FULAErrorDomain", code: 1001, userInfo: [NSLocalizedDescriptionKey: "Fula instance is not initialized"])
|
|
1633
|
-
DispatchQueue.main.async {
|
|
1634
|
-
reject("ERR_FULA", "Fula not initialized", error)
|
|
1635
|
-
}
|
|
1636
|
-
return
|
|
1637
|
-
}
|
|
1638
|
-
|
|
1639
|
-
let result = try fula.listPlugins()
|
|
1640
|
-
guard let resultString = result.toUTF8String() else {
|
|
1641
|
-
let error = NSError(domain: "FULAErrorDomain", code: 1002, userInfo: [NSLocalizedDescriptionKey: "Failed to convert plugin list to string"])
|
|
1642
|
-
DispatchQueue.main.async {
|
|
1643
|
-
reject("ERR_FULA", "Plugin List Conversion Error", error)
|
|
1644
|
-
}
|
|
1645
|
-
return
|
|
1646
|
-
}
|
|
1647
|
-
|
|
1648
|
-
DispatchQueue.main.async {
|
|
1649
|
-
resolve(resultString)
|
|
1650
|
-
}
|
|
1651
|
-
} catch let error {
|
|
1652
|
-
print("listPlugins", error.localizedDescription)
|
|
1653
|
-
DispatchQueue.main.async {
|
|
1654
|
-
reject("ERR_FULA", "listPlugins failed", error)
|
|
1655
|
-
}
|
|
1656
|
-
}
|
|
1657
|
-
}
|
|
1658
|
-
}
|
|
1659
|
-
|
|
1660
|
-
@objc(listActivePlugins:withRejecter:)
|
|
1661
|
-
func listActivePlugins(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1662
|
-
DispatchQueue.global(qos: .background).async {
|
|
1663
|
-
do {
|
|
1664
|
-
guard let fula = self.fula else {
|
|
1665
|
-
let error = NSError(domain: "FULAErrorDomain", code: 1001, userInfo: [NSLocalizedDescriptionKey: "Fula instance is not initialized"])
|
|
1666
|
-
DispatchQueue.main.async {
|
|
1667
|
-
reject("ERR_FULA", "Fula not initialized", error)
|
|
1668
|
-
}
|
|
1669
|
-
return
|
|
1670
|
-
}
|
|
1671
|
-
|
|
1672
|
-
let result: Data
|
|
1673
|
-
do {
|
|
1674
|
-
result = try fula.listActivePlugins()
|
|
1675
|
-
} catch {
|
|
1676
|
-
print("Error listing active plugins: \(error)")
|
|
1677
|
-
DispatchQueue.main.async {
|
|
1678
|
-
reject("ERR_FULA", "Failed to list active plugins", error)
|
|
1679
|
-
}
|
|
1680
|
-
return
|
|
1681
|
-
}
|
|
1682
|
-
|
|
1683
|
-
guard !result.isEmpty else {
|
|
1684
|
-
let error = NSError(domain: "FULAErrorDomain", code: 1002, userInfo: [NSLocalizedDescriptionKey: "Active plugin list is empty"])
|
|
1685
|
-
DispatchQueue.main.async {
|
|
1686
|
-
reject("ERR_FULA", "Empty Active Plugin List", error)
|
|
1687
|
-
}
|
|
1688
|
-
return
|
|
1689
|
-
}
|
|
1690
|
-
|
|
1691
|
-
guard let resultString = String(data: result, encoding: .utf8) else {
|
|
1692
|
-
let error = NSError(domain: "FULAErrorDomain", code: 1003, userInfo: [NSLocalizedDescriptionKey: "Failed to convert active plugin list to string"])
|
|
1693
|
-
DispatchQueue.main.async {
|
|
1694
|
-
reject("ERR_FULA", "Active Plugin List Conversion Error", error)
|
|
1695
|
-
}
|
|
1696
|
-
return
|
|
1697
|
-
}
|
|
1698
|
-
|
|
1699
|
-
DispatchQueue.main.async {
|
|
1700
|
-
resolve(resultString)
|
|
1701
|
-
}
|
|
1702
|
-
} catch let error {
|
|
1703
|
-
print("listActivePlugins unexpected error:", error.localizedDescription)
|
|
1704
|
-
DispatchQueue.main.async {
|
|
1705
|
-
reject("ERR_FULA", "listActivePlugins failed unexpectedly", error)
|
|
1706
|
-
}
|
|
1707
|
-
}
|
|
1708
|
-
}
|
|
1709
|
-
}
|
|
1710
|
-
|
|
1711
|
-
@objc(installPlugin:withParams:withResolver:withRejecter:)
|
|
1712
|
-
func installPlugin(pluginName: String, params: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1713
|
-
DispatchQueue.global(qos: .background).async {
|
|
1714
|
-
do {
|
|
1715
|
-
guard let fula = self.fula else {
|
|
1716
|
-
let error = NSError(domain: "FULAErrorDomain", code: 1001, userInfo: [NSLocalizedDescriptionKey: "Fula instance is not initialized"])
|
|
1717
|
-
DispatchQueue.main.async {
|
|
1718
|
-
reject("ERR_FULA_NOT_INITIALIZED", "Fula not initialized", error)
|
|
1719
|
-
}
|
|
1720
|
-
return
|
|
1721
|
-
}
|
|
1722
|
-
|
|
1723
|
-
let result = try fula.installPlugin(pluginName, params: params)
|
|
1724
|
-
guard let resultString = result.toUTF8String() else {
|
|
1725
|
-
let error = NSError(domain: "FULAErrorDomain", code: 1002, userInfo: [NSLocalizedDescriptionKey: "Failed to convert install result to string"])
|
|
1726
|
-
DispatchQueue.main.async {
|
|
1727
|
-
reject("ERR_FULA_RESULT_CONVERSION", "Install Result Conversion Error", error)
|
|
1728
|
-
}
|
|
1729
|
-
return
|
|
1730
|
-
}
|
|
1731
|
-
|
|
1732
|
-
DispatchQueue.main.async {
|
|
1733
|
-
resolve(resultString)
|
|
1734
|
-
}
|
|
1735
|
-
} catch let error {
|
|
1736
|
-
print("installPlugin error:", error.localizedDescription)
|
|
1737
|
-
DispatchQueue.main.async {
|
|
1738
|
-
reject("ERR_FULA_INSTALL_PLUGIN", "Failed to install plugin: \(pluginName)", error)
|
|
1739
|
-
}
|
|
1740
|
-
}
|
|
1741
|
-
}
|
|
1742
|
-
}
|
|
1743
|
-
|
|
1744
|
-
@objc(uninstallPlugin:withResolver:withRejecter:)
|
|
1745
|
-
func uninstallPlugin(pluginName: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1746
|
-
DispatchQueue.global(qos: .background).async {
|
|
1747
|
-
do {
|
|
1748
|
-
guard let fula = self.fula else {
|
|
1749
|
-
let error = NSError(domain: "FULAErrorDomain", code: 1001, userInfo: [NSLocalizedDescriptionKey: "Fula instance is not initialized"])
|
|
1750
|
-
DispatchQueue.main.async {
|
|
1751
|
-
reject("ERR_FULA_NOT_INITIALIZED", "Fula not initialized", error)
|
|
1752
|
-
}
|
|
1753
|
-
return
|
|
1754
|
-
}
|
|
1755
|
-
|
|
1756
|
-
let result = try fula.uninstallPlugin(pluginName)
|
|
1757
|
-
guard let resultString = result.toUTF8String() else {
|
|
1758
|
-
let error = NSError(domain: "FULAErrorDomain", code: 1002, userInfo: [NSLocalizedDescriptionKey: "Failed to convert uninstall result to string"])
|
|
1759
|
-
DispatchQueue.main.async {
|
|
1760
|
-
reject("ERR_FULA_RESULT_CONVERSION", "Uninstall Result Conversion Error", error)
|
|
1761
|
-
}
|
|
1762
|
-
return
|
|
1763
|
-
}
|
|
1764
|
-
|
|
1765
|
-
DispatchQueue.main.async {
|
|
1766
|
-
resolve(resultString)
|
|
1767
|
-
}
|
|
1768
|
-
} catch let error {
|
|
1769
|
-
print("uninstallPlugin error:", error.localizedDescription)
|
|
1770
|
-
DispatchQueue.main.async {
|
|
1771
|
-
reject("ERR_FULA_UNINSTALL_PLUGIN", "Failed to uninstall plugin: \(pluginName)", error)
|
|
1772
|
-
}
|
|
1773
|
-
}
|
|
1774
|
-
}
|
|
1775
|
-
}
|
|
1776
|
-
|
|
1777
|
-
@objc(showPluginStatus:withLines:withResolver:withRejecter:)
|
|
1778
|
-
func showPluginStatus(pluginName: String, lines: Int, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1779
|
-
DispatchQueue.global(qos: .background).async {
|
|
1780
|
-
do {
|
|
1781
|
-
guard let fula = self.fula else {
|
|
1782
|
-
let error = NSError(domain: "FULAErrorDomain", code: 1001, userInfo: [NSLocalizedDescriptionKey: "Fula instance is not initialized"])
|
|
1783
|
-
DispatchQueue.main.async {
|
|
1784
|
-
reject("ERR_FULA_NOT_INITIALIZED", "Fula not initialized", error)
|
|
1785
|
-
}
|
|
1786
|
-
return
|
|
1787
|
-
}
|
|
1788
|
-
|
|
1789
|
-
let result: Data
|
|
1790
|
-
do {
|
|
1791
|
-
result = try fula.showPluginStatus(pluginName, lines: lines)
|
|
1792
|
-
} catch {
|
|
1793
|
-
print("Error showing plugin status: \(error)")
|
|
1794
|
-
DispatchQueue.main.async {
|
|
1795
|
-
reject("ERR_FULA_SHOW_PLUGIN_STATUS", "Failed to show plugin status", error)
|
|
1796
|
-
}
|
|
1797
|
-
return
|
|
1798
|
-
}
|
|
1799
|
-
|
|
1800
|
-
guard !result.isEmpty else {
|
|
1801
|
-
let error = NSError(domain: "FULAErrorDomain", code: 1002, userInfo: [NSLocalizedDescriptionKey: "Plugin status result is empty"])
|
|
1802
|
-
DispatchQueue.main.async {
|
|
1803
|
-
reject("ERR_FULA_EMPTY_RESULT", "Empty Plugin Status Result", error)
|
|
1804
|
-
}
|
|
1805
|
-
return
|
|
1806
|
-
}
|
|
1807
|
-
|
|
1808
|
-
guard let resultString = String(data: result, encoding: .utf8) else {
|
|
1809
|
-
let error = NSError(domain: "FULAErrorDomain", code: 1003, userInfo: [NSLocalizedDescriptionKey: "Failed to convert plugin status to string"])
|
|
1810
|
-
DispatchQueue.main.async {
|
|
1811
|
-
reject("ERR_FULA_RESULT_CONVERSION", "Plugin Status Conversion Error", error)
|
|
1812
|
-
}
|
|
1813
|
-
return
|
|
1814
|
-
}
|
|
1815
|
-
|
|
1816
|
-
DispatchQueue.main.async {
|
|
1817
|
-
resolve(resultString)
|
|
1818
|
-
}
|
|
1819
|
-
} catch {
|
|
1820
|
-
print("showPluginStatus unexpected error:", error.localizedDescription)
|
|
1821
|
-
DispatchQueue.main.async {
|
|
1822
|
-
reject("ERR_FULA_SHOW_PLUGIN_STATUS", "showPluginStatus failed unexpectedly", error)
|
|
1823
|
-
}
|
|
1824
|
-
}
|
|
1825
|
-
}
|
|
1826
|
-
}
|
|
1827
|
-
|
|
1828
|
-
@objc(getInstallOutput:withParams:withResolver:withRejecter:)
|
|
1829
|
-
func getInstallOutput(pluginName: String, params: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1830
|
-
DispatchQueue.global(qos: .background).async {
|
|
1831
|
-
do {
|
|
1832
|
-
guard let fula = self.fula else {
|
|
1833
|
-
let error = NSError(domain: "FULAErrorDomain", code: 1001, userInfo: [NSLocalizedDescriptionKey: "Fula instance is not initialized"])
|
|
1834
|
-
DispatchQueue.main.async {
|
|
1835
|
-
reject("ERR_FULA_NOT_INITIALIZED", "Fula not initialized", error)
|
|
1836
|
-
}
|
|
1837
|
-
return
|
|
1838
|
-
}
|
|
1839
|
-
|
|
1840
|
-
let result: Data
|
|
1841
|
-
do {
|
|
1842
|
-
result = try fula.getInstallOutput(pluginName, params: params)
|
|
1843
|
-
} catch {
|
|
1844
|
-
print("Error getting install output: \(error)")
|
|
1845
|
-
DispatchQueue.main.async {
|
|
1846
|
-
reject("ERR_FULA_GET_INSTALL_OUTPUT", "Failed to get install output", error)
|
|
1847
|
-
}
|
|
1848
|
-
return
|
|
1849
|
-
}
|
|
1850
|
-
|
|
1851
|
-
guard !result.isEmpty else {
|
|
1852
|
-
let error = NSError(domain: "FULAErrorDomain", code: 1002, userInfo: [NSLocalizedDescriptionKey: "Install output is empty"])
|
|
1853
|
-
DispatchQueue.main.async {
|
|
1854
|
-
reject("ERR_FULA_EMPTY_RESULT", "Empty Install Output", error)
|
|
1855
|
-
}
|
|
1856
|
-
return
|
|
1857
|
-
}
|
|
1858
|
-
|
|
1859
|
-
guard let resultString = String(data: result, encoding: .utf8) else {
|
|
1860
|
-
let error = NSError(domain: "FULAErrorDomain", code: 1003, userInfo: [NSLocalizedDescriptionKey: "Failed to convert install output to string"])
|
|
1861
|
-
DispatchQueue.main.async {
|
|
1862
|
-
reject("ERR_FULA_RESULT_CONVERSION", "Install Output Conversion Error", error)
|
|
1863
|
-
}
|
|
1864
|
-
return
|
|
1865
|
-
}
|
|
1866
|
-
|
|
1867
|
-
DispatchQueue.main.async {
|
|
1868
|
-
resolve(resultString)
|
|
1869
|
-
}
|
|
1870
|
-
} catch {
|
|
1871
|
-
print("getInstallOutput unexpected error:", error.localizedDescription)
|
|
1872
|
-
DispatchQueue.main.async {
|
|
1873
|
-
reject("ERR_FULA_GET_INSTALL_OUTPUT", "getInstallOutput failed unexpectedly", error)
|
|
1874
|
-
}
|
|
1875
|
-
}
|
|
1876
|
-
}
|
|
1877
|
-
}
|
|
1878
|
-
|
|
1879
|
-
@objc(getInstallStatus:withResolver:withRejecter:)
|
|
1880
|
-
func getInstallStatus(pluginName: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1881
|
-
DispatchQueue.global(qos: .background).async {
|
|
1882
|
-
do {
|
|
1883
|
-
guard let fula = self.fula else {
|
|
1884
|
-
let error = NSError(domain: "FULAErrorDomain", code: 1001, userInfo: [NSLocalizedDescriptionKey: "Fula instance is not initialized"])
|
|
1885
|
-
DispatchQueue.main.async {
|
|
1886
|
-
reject("ERR_FULA_NOT_INITIALIZED", "Fula not initialized", error)
|
|
1887
|
-
}
|
|
1888
|
-
return
|
|
1889
|
-
}
|
|
1890
|
-
|
|
1891
|
-
let result: Data
|
|
1892
|
-
do {
|
|
1893
|
-
result = try fula.getInstallStatus(pluginName)
|
|
1894
|
-
} catch {
|
|
1895
|
-
print("Error getting install status: \(error)")
|
|
1896
|
-
DispatchQueue.main.async {
|
|
1897
|
-
reject("ERR_FULA_GET_INSTALL_STATUS", "Failed to get install status", error)
|
|
1898
|
-
}
|
|
1899
|
-
return
|
|
1900
|
-
}
|
|
1901
|
-
|
|
1902
|
-
guard !result.isEmpty else {
|
|
1903
|
-
let error = NSError(domain: "FULAErrorDomain", code: 1002, userInfo: [NSLocalizedDescriptionKey: "Install status result is empty"])
|
|
1904
|
-
DispatchQueue.main.async {
|
|
1905
|
-
reject("ERR_FULA_EMPTY_RESULT", "Empty Install Status Result", error)
|
|
1906
|
-
}
|
|
1907
|
-
return
|
|
1908
|
-
}
|
|
1909
|
-
|
|
1910
|
-
guard let resultString = String(data: result, encoding: .utf8) else {
|
|
1911
|
-
let error = NSError(domain: "FULAErrorDomain", code: 1003, userInfo: [NSLocalizedDescriptionKey: "Failed to convert install status to string"])
|
|
1912
|
-
DispatchQueue.main.async {
|
|
1913
|
-
reject("ERR_FULA_RESULT_CONVERSION", "Install Status Conversion Error", error)
|
|
1914
|
-
}
|
|
1915
|
-
return
|
|
1916
|
-
}
|
|
1917
|
-
|
|
1918
|
-
DispatchQueue.main.async {
|
|
1919
|
-
resolve(resultString)
|
|
1920
|
-
}
|
|
1921
|
-
} catch {
|
|
1922
|
-
print("getInstallStatus unexpected error:", error.localizedDescription)
|
|
1923
|
-
DispatchQueue.main.async {
|
|
1924
|
-
reject("ERR_FULA_GET_INSTALL_STATUS", "getInstallStatus failed unexpectedly", error)
|
|
1925
|
-
}
|
|
1926
|
-
}
|
|
1927
|
-
}
|
|
1928
|
-
}
|
|
1929
|
-
|
|
1930
|
-
@objc(updatePlugin:withResolver:withRejecter:)
|
|
1931
|
-
func updatePlugin(pluginName: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1932
|
-
DispatchQueue.global(qos: .background).async {
|
|
1933
|
-
do {
|
|
1934
|
-
guard let fula = self.fula else {
|
|
1935
|
-
let error = NSError(domain: "FULAErrorDomain", code: 1001, userInfo: [NSLocalizedDescriptionKey: "Fula instance is not initialized"])
|
|
1936
|
-
DispatchQueue.main.async {
|
|
1937
|
-
reject("ERR_FULA_NOT_INITIALIZED", "Fula not initialized", error)
|
|
1938
|
-
}
|
|
1939
|
-
return
|
|
1940
|
-
}
|
|
1941
|
-
|
|
1942
|
-
let result: Data
|
|
1943
|
-
do {
|
|
1944
|
-
result = try fula.updatePlugin(pluginName)
|
|
1945
|
-
} catch {
|
|
1946
|
-
print("Error updating plugin: \(error)")
|
|
1947
|
-
DispatchQueue.main.async {
|
|
1948
|
-
reject("ERR_FULA_UPDATE_PLUGIN", "Failed to update plugin: \(pluginName)", error)
|
|
1949
|
-
}
|
|
1950
|
-
return
|
|
1951
|
-
}
|
|
1952
|
-
|
|
1953
|
-
guard !result.isEmpty else {
|
|
1954
|
-
let error = NSError(domain: "FULAErrorDomain", code: 1002, userInfo: [NSLocalizedDescriptionKey: "Update plugin result is empty"])
|
|
1955
|
-
DispatchQueue.main.async {
|
|
1956
|
-
reject("ERR_FULA_EMPTY_RESULT", "Empty Update Plugin Result", error)
|
|
1957
|
-
}
|
|
1958
|
-
return
|
|
1959
|
-
}
|
|
1960
|
-
|
|
1961
|
-
guard let resultString = String(data: result, encoding: .utf8) else {
|
|
1962
|
-
let error = NSError(domain: "FULAErrorDomain", code: 1003, userInfo: [NSLocalizedDescriptionKey: "Failed to convert update plugin result to string"])
|
|
1963
|
-
DispatchQueue.main.async {
|
|
1964
|
-
reject("ERR_FULA_RESULT_CONVERSION", "Update Plugin Result Conversion Error", error)
|
|
1965
|
-
}
|
|
1966
|
-
return
|
|
1967
|
-
}
|
|
1968
|
-
|
|
1969
|
-
DispatchQueue.main.async {
|
|
1970
|
-
resolve(resultString)
|
|
1971
|
-
}
|
|
1972
|
-
} catch {
|
|
1973
|
-
print("updatePlugin unexpected error:", error.localizedDescription)
|
|
1974
|
-
DispatchQueue.main.async {
|
|
1975
|
-
reject("ERR_FULA_UPDATE_PLUGIN", "updatePlugin failed unexpectedly", error)
|
|
1976
|
-
}
|
|
1977
|
-
}
|
|
1978
|
-
}
|
|
1979
|
-
}
|
|
1980
|
-
|
|
1981
|
-
@objc(replicateInPool:withAccount:withPoolID:withResolver:withRejecter:)
|
|
1982
|
-
func replicateInPool(cidArray: [String], account: String, poolID: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1983
|
-
DispatchQueue.global(qos: .background).async {
|
|
1984
|
-
do {
|
|
1985
|
-
guard let fula = self.fula else {
|
|
1986
|
-
let error = NSError(domain: "FULAErrorDomain", code: 1001, userInfo: [NSLocalizedDescriptionKey: "Fula instance is not initialized"])
|
|
1987
|
-
DispatchQueue.main.async {
|
|
1988
|
-
reject("ERR_FULA_NOT_INITIALIZED", "Fula not initialized", error)
|
|
1989
|
-
}
|
|
1990
|
-
return
|
|
1991
|
-
}
|
|
1992
|
-
|
|
1993
|
-
guard let poolIDLong = Int64(poolID) else {
|
|
1994
|
-
let error = NSError(domain: "FULAErrorDomain", code: 1002, userInfo: [NSLocalizedDescriptionKey: "Invalid poolID"])
|
|
1995
|
-
DispatchQueue.main.async {
|
|
1996
|
-
reject("ERR_FULA_INVALID_POOL_ID", "Invalid poolID", error)
|
|
1997
|
-
}
|
|
1998
|
-
return
|
|
1999
|
-
}
|
|
2000
|
-
|
|
2001
|
-
guard let poolIDInt = Int(exactly: poolIDLong) else {
|
|
2002
|
-
let error = NSError(domain: "FULAErrorDomain", code: 1003, userInfo: [NSLocalizedDescriptionKey: "PoolID is too large for Int"])
|
|
2003
|
-
DispatchQueue.main.async {
|
|
2004
|
-
reject("ERR_FULA_POOL_ID_OVERFLOW", "PoolID is too large", error)
|
|
2005
|
-
}
|
|
2006
|
-
return
|
|
2007
|
-
}
|
|
2008
|
-
|
|
2009
|
-
let cidString = cidArray.joined(separator: "|")
|
|
2010
|
-
guard let cidsBytes = cidString.data(using: .utf8) else {
|
|
2011
|
-
let error = NSError(domain: "FULAErrorDomain", code: 1004, userInfo: [NSLocalizedDescriptionKey: "Failed to encode CIDs as data"])
|
|
2012
|
-
DispatchQueue.main.async {
|
|
2013
|
-
reject("ERR_FULA_CID_ENCODING", "Failed to encode CIDs", error)
|
|
2014
|
-
}
|
|
2015
|
-
return
|
|
2016
|
-
}
|
|
2017
|
-
|
|
2018
|
-
let result: Data
|
|
2019
|
-
do {
|
|
2020
|
-
if let replicationResult = try fula.replicate(inPool: cidsBytes, account: account, poolID: poolIDInt) {
|
|
2021
|
-
result = replicationResult
|
|
2022
|
-
} else {
|
|
2023
|
-
throw NSError(domain: "FULAErrorDomain", code: 1007, userInfo: [NSLocalizedDescriptionKey: "Replication result is nil"])
|
|
2024
|
-
}
|
|
2025
|
-
} catch {
|
|
2026
|
-
print("Error replicating in pool: \(error)")
|
|
2027
|
-
DispatchQueue.main.async {
|
|
2028
|
-
reject("ERR_FULA_REPLICATION", "Failed to replicate in pool", error)
|
|
2029
|
-
}
|
|
2030
|
-
return
|
|
2031
|
-
}
|
|
2032
|
-
|
|
2033
|
-
guard !result.isEmpty else {
|
|
2034
|
-
let error = NSError(domain: "FULAErrorDomain", code: 1005, userInfo: [NSLocalizedDescriptionKey: "Replication result is empty"])
|
|
2035
|
-
DispatchQueue.main.async {
|
|
2036
|
-
reject("ERR_FULA_EMPTY_RESULT", "Empty replication result", error)
|
|
2037
|
-
}
|
|
2038
|
-
return
|
|
2039
|
-
}
|
|
2040
|
-
|
|
2041
|
-
guard let resultString = String(data: result, encoding: .utf8) else {
|
|
2042
|
-
let error = NSError(domain: "FULAErrorDomain", code: 1006, userInfo: [NSLocalizedDescriptionKey: "Failed to decode result data to string"])
|
|
2043
|
-
DispatchQueue.main.async {
|
|
2044
|
-
reject("ERR_FULA_RESULT_DECODING", "Failed to decode result", error)
|
|
2045
|
-
}
|
|
2046
|
-
return
|
|
2047
|
-
}
|
|
2048
|
-
|
|
2049
|
-
DispatchQueue.main.async {
|
|
2050
|
-
resolve(resultString)
|
|
2051
|
-
}
|
|
2052
|
-
} catch {
|
|
2053
|
-
print("replicateInPool unexpected error:", error.localizedDescription)
|
|
2054
|
-
DispatchQueue.main.async {
|
|
2055
|
-
reject("ERR_FULA_REPLICATE_IN_POOL", "replicateInPool failed unexpectedly", error)
|
|
2056
|
-
}
|
|
2057
|
-
}
|
|
2058
|
-
}
|
|
2059
|
-
}
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
1
|
+
import Foundation
|
|
2
|
+
import Foundation.NSDate // for TimeInterval
|
|
3
|
+
import CommonCrypto
|
|
4
|
+
import Wnfs
|
|
5
|
+
import Fula
|
|
6
|
+
import os.log
|
|
7
|
+
|
|
8
|
+
extension OSLog {
|
|
9
|
+
|
|
10
|
+
private static var subsystem = Bundle.main.bundleIdentifier!
|
|
11
|
+
|
|
12
|
+
/// Logs the view cycles like a view that appeared.
|
|
13
|
+
static let viewCycle = OSLog(subsystem: subsystem, category: "viewcycle")
|
|
14
|
+
|
|
15
|
+
/// All logs related to tracking and analytics.
|
|
16
|
+
static let statistics = OSLog(subsystem: subsystem, category: "statistics")
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
extension OSLog {
|
|
20
|
+
|
|
21
|
+
func info(_ msg: String, _ args: CVarArg...) {
|
|
22
|
+
os_log("%{public}@", log: self, type: .info, msg)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
func error(_ msg: String, _ args: CVarArg...) {
|
|
26
|
+
os_log("%{public}@", log: self, type: .error, msg)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// ... (more methods for different log levels, if needed)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@objc(FulaModule)
|
|
34
|
+
class FulaModule: NSObject {
|
|
35
|
+
public let NAME: String = "FulaModule"
|
|
36
|
+
var fula: FulamobileClient?
|
|
37
|
+
|
|
38
|
+
var client: Client?
|
|
39
|
+
var wnfs: Wnfs?
|
|
40
|
+
var fulaConfig: FulamobileConfig?
|
|
41
|
+
var appDir: URL
|
|
42
|
+
var fulaStorePath: String
|
|
43
|
+
// Related to the Wnfs library
|
|
44
|
+
var rootCid: Cid?
|
|
45
|
+
var wnfsKey: Data?
|
|
46
|
+
let userDataHelper = UserDataHelper()
|
|
47
|
+
var secretKeyGlobal: Array<UInt8>?
|
|
48
|
+
var identityEncryptedGlobal: String?
|
|
49
|
+
static let PRIVATE_KEY_STORE_ID = "PRIVATE_KEY"
|
|
50
|
+
|
|
51
|
+
// FIXME: Hardcoded ,fula should remove all the codec arguments as the rs-wnfs library removed its usage now.
|
|
52
|
+
static let CODEC_DAG_CBOR = Int(113)
|
|
53
|
+
|
|
54
|
+
enum MyError: Error {
|
|
55
|
+
case runtimeError(String)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
@objc(Client)
|
|
59
|
+
public class Client: NSObject {
|
|
60
|
+
let internalClient: FulamobileClient
|
|
61
|
+
|
|
62
|
+
init(clientInput: FulamobileClient) {
|
|
63
|
+
internalClient = clientInput
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
func get(_ cid: Data) throws -> Data {
|
|
67
|
+
do {
|
|
68
|
+
print(String(format: "ReactNative get cid: %s", cid.toHex()))
|
|
69
|
+
return try internalClient.get(cid)
|
|
70
|
+
} catch let error {
|
|
71
|
+
throw error
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
func put(_ cid: Data, _ data: Data) throws -> Void {
|
|
76
|
+
do {
|
|
77
|
+
print(String(format: "ReactNative put(%s) data: %s", cid.toHex(), data.toHex()))
|
|
78
|
+
try internalClient.put(data, codec: 0xFF & Int64(cid[1]))
|
|
79
|
+
} catch let error {
|
|
80
|
+
print("ReactNative put: ", error.localizedDescription)
|
|
81
|
+
throw error
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
override init() {
|
|
86
|
+
|
|
87
|
+
self.appDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
|
|
88
|
+
let fulaStoreURL = appDir.appendingPathComponent("/fula")
|
|
89
|
+
|
|
90
|
+
self.fulaStorePath = fulaStoreURL.path
|
|
91
|
+
let fileManager = FileManager.default
|
|
92
|
+
var success = true
|
|
93
|
+
if !fileManager.fileExists(atPath: fulaStorePath) {
|
|
94
|
+
do{
|
|
95
|
+
try fileManager.createDirectory(atPath: fulaStorePath, withIntermediateDirectories: true)
|
|
96
|
+
}catch let error{
|
|
97
|
+
print(error.localizedDescription)
|
|
98
|
+
success = false
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
}
|
|
102
|
+
if success {
|
|
103
|
+
print("Fula store folder created")
|
|
104
|
+
} else {
|
|
105
|
+
print("Unable to create fula store folder!")
|
|
106
|
+
|
|
107
|
+
}
|
|
108
|
+
super.init()
|
|
109
|
+
|
|
110
|
+
}
|
|
111
|
+
func convertConfigToJson(config: Cid) -> String {
|
|
112
|
+
return String(format: "{\"cid\": \"%@\"}", config)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
func getName() -> String {
|
|
116
|
+
return NAME
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
func toByte(_ input: String) -> Data {
|
|
120
|
+
return input.data(using: .utf8)!
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
func stringArrToIntArr(_ s: Array<String>) -> Array<Int> {
|
|
125
|
+
return s.map { Int($0)!}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
func convertIntToByte(_ s: Array<Int>) -> Array<UInt8> {
|
|
129
|
+
return s.map { UInt8(exactly: $0)!}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
func convertStringToByte(_ input: String) -> Array<UInt8> {
|
|
133
|
+
let splitted = input.split(separator: ",").map { String($0) }
|
|
134
|
+
let keyInt = stringArrToIntArr(splitted)
|
|
135
|
+
return convertIntToByte(keyInt)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
@objc func applicationWillResignActive() {
|
|
139
|
+
// Log that the app will resign active
|
|
140
|
+
os_log("Application will resign active", log: OSLog.viewCycle, type: .info)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
@objc func applicationDidEnterBackground() {
|
|
144
|
+
// Log that the app has entered the background
|
|
145
|
+
os_log("Application did enter background", log: OSLog.viewCycle, type: .info)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
@objc func applicationWillTerminate() {
|
|
149
|
+
// Attempt to shut down Fula cleanly (similar to onHostDestroy)
|
|
150
|
+
os_log("Application will terminate - shutting down Fula", log: OSLog.viewCycle, type: .info)
|
|
151
|
+
do {
|
|
152
|
+
if let fulaClient = self.fula {
|
|
153
|
+
try fulaClient.shutdown()
|
|
154
|
+
os_log("Fula shutdown successfully.", log: OSLog.viewCycle, type: .info)
|
|
155
|
+
}
|
|
156
|
+
} catch {
|
|
157
|
+
os_log("Error shutting down Fula: %{public}@", log: OSLog.viewCycle, type: .error, String(describing: error))
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
@objc(registerLifecycleListener:withRejecter:)
|
|
162
|
+
func registerLifecycleListener(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
163
|
+
NotificationCenter.default.addObserver(
|
|
164
|
+
self,
|
|
165
|
+
selector: #selector(applicationWillResignActive),
|
|
166
|
+
name: UIApplication.willResignActiveNotification,
|
|
167
|
+
object: nil)
|
|
168
|
+
|
|
169
|
+
NotificationCenter.default.addObserver(
|
|
170
|
+
self,
|
|
171
|
+
selector: #selector(applicationDidEnterBackground),
|
|
172
|
+
name: UIApplication.didEnterBackgroundNotification,
|
|
173
|
+
object: nil)
|
|
174
|
+
|
|
175
|
+
NotificationCenter.default.addObserver(
|
|
176
|
+
self,
|
|
177
|
+
selector: #selector(applicationWillTerminate),
|
|
178
|
+
name: UIApplication.willTerminateNotification,
|
|
179
|
+
object: nil)
|
|
180
|
+
|
|
181
|
+
// Assuming the operation is always successful
|
|
182
|
+
resolve(true)
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
deinit {
|
|
186
|
+
NotificationCenter.default.removeObserver(self)
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
@objc(checkConnection:withResolver:withRejecter:)
|
|
190
|
+
func checkConnection(timeout: NSNumber, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
191
|
+
NSLog("ReactNative checkConnection started with timeout=\(timeout)")
|
|
192
|
+
|
|
193
|
+
if let timeoutInt = timeout as? Int {
|
|
194
|
+
if self.fula != nil {
|
|
195
|
+
DispatchQueue.global(qos: .default).async {
|
|
196
|
+
do {
|
|
197
|
+
let connectionStatus = try self.checkConnectionInternal(timeout: timeoutInt)
|
|
198
|
+
NSLog("ReactNative checkConnection ended \(connectionStatus)")
|
|
199
|
+
resolve(connectionStatus)
|
|
200
|
+
}
|
|
201
|
+
catch let error {
|
|
202
|
+
NSLog("ReactNative checkConnection failed with Error: \(error.localizedDescription)")
|
|
203
|
+
resolve(false)
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
} else {
|
|
207
|
+
NSLog("ReactNative checkConnection fula is null")
|
|
208
|
+
resolve(false)
|
|
209
|
+
}
|
|
210
|
+
} else {
|
|
211
|
+
OSLog.viewCycle.error("ReactNative checkConnection - invalid timeout value")
|
|
212
|
+
reject("ERR_INVALID_TIMEOUT", "Invalid timeout value", nil)
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
@objc(newClient:withStorePath:withBloxAddr:withExchange:withAutoFlush:withUseRelay:withRefresh:withResolver:withRejecter:)
|
|
218
|
+
func newClient(identityString: String, storePath: String, bloxAddr: String, exchange: String, autoFlush: Bool, useRelay: Bool, refresh: Bool, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
219
|
+
print("ReactNative", "newClient storePath= " , storePath , " bloxAddr= " , bloxAddr , " exchange= " , exchange , " autoFlush= " , autoFlush , " useRelay= " , useRelay , " refresh= " , refresh)
|
|
220
|
+
do {
|
|
221
|
+
print("ReactNative", "newClient storePath= ", storePath)
|
|
222
|
+
let identity = toByte(identityString)
|
|
223
|
+
print("ReactNative", "newClient identity= ", identityString)
|
|
224
|
+
try newClientInternal(identity: identity, storePath: storePath, bloxAddr: bloxAddr, exchange: exchange, autoFlush: autoFlush, useRelay: useRelay, refresh: refresh)
|
|
225
|
+
let peerId = self.fula?.id_()
|
|
226
|
+
resolve(peerId)
|
|
227
|
+
} catch let error {
|
|
228
|
+
print("ReactNative", "newClient failed with Error: ", error.localizedDescription)
|
|
229
|
+
reject("ERR_FULA", "Can't create client", error)
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
@objc(isReady:withResolver:withRejecter:)
|
|
235
|
+
func isReady(filesystemCheck: Bool, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void{
|
|
236
|
+
print("ReactNative", "isReady started")
|
|
237
|
+
var initialized = false
|
|
238
|
+
do {
|
|
239
|
+
if (self.fula != nil && !self.fula!.id_().isEmpty) {
|
|
240
|
+
if (filesystemCheck) {
|
|
241
|
+
if (self.client != nil && rootCid != nil && !rootCid!.isEmpty) {
|
|
242
|
+
initialized = true
|
|
243
|
+
}
|
|
244
|
+
} else {
|
|
245
|
+
initialized = true
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
resolve(initialized)
|
|
249
|
+
} catch let error {
|
|
250
|
+
print("ReactNative", "isReady failed with Error: " + error.localizedDescription)
|
|
251
|
+
reject("ERR_FULA", "Check if fula is ready", error)
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
//TODO: we should consider refactor the name of this \
|
|
256
|
+
// function to be compatible with the android version.
|
|
257
|
+
@objc(initFula:withStorePath:withBloxAddr:withExchange:withAutoFlush:withRootConfig:withUseRelay:withRefresh:withResolver:withRejecter:)
|
|
258
|
+
func initFula(identityString: String, storePath: String, bloxAddr: String, exchange: String, autoFlush: Bool, rootConfig: String, useRelay: Bool, refresh: Bool, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
259
|
+
|
|
260
|
+
NSLog("ReactNative - init started")
|
|
261
|
+
|
|
262
|
+
do {
|
|
263
|
+
|
|
264
|
+
var resultData = Dictionary<String, String>()
|
|
265
|
+
NSLog("ReactNative init storePath= \(storePath)")
|
|
266
|
+
let identity = self.toByte(identityString)
|
|
267
|
+
NSLog("ReactNative init identity= \(identityString)")
|
|
268
|
+
let obj = try initInternal(identity: identity, storePath: storePath, bloxAddr: bloxAddr, exchange: exchange, autoFlush: autoFlush, _rootCid: rootConfig, useRelay: useRelay, refresh: refresh)
|
|
269
|
+
NSLog("ReactNative init object created: [ \(obj[0]), \(obj[1]), \(obj[2]) ]")
|
|
270
|
+
resultData["peerId"] = obj[0]
|
|
271
|
+
resultData["rootCid"] = obj[1]
|
|
272
|
+
resultData["wnfs_key"] = obj[2]
|
|
273
|
+
resolve(resultData as NSDictionary)
|
|
274
|
+
|
|
275
|
+
} catch let error {
|
|
276
|
+
NSLog("ReactNative init failed with Error: \(error.localizedDescription)")
|
|
277
|
+
reject("ERR_FULA", "init failed", error)
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
@objc(logout:withStorePath:withResolver:withRejecter:)
|
|
283
|
+
func logout(identityString: String, storePath: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void{
|
|
284
|
+
|
|
285
|
+
print("ReactNative", "logout started")
|
|
286
|
+
do {
|
|
287
|
+
let identity = toByte(identityString)
|
|
288
|
+
try logoutInternal(identity: identity, _storePath: storePath)
|
|
289
|
+
print("ReactNative", "logout completed")
|
|
290
|
+
resolve("")
|
|
291
|
+
|
|
292
|
+
} catch let error {
|
|
293
|
+
print("ReactNative", "logout failed with Error: ", error.localizedDescription)
|
|
294
|
+
reject("ERR_FULA", "logout failed", error)
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
func checkConnectionInternal(timeout: Int) throws -> Bool {
|
|
300
|
+
NSLog("ReactNative checkConnectionInternal started with timeout: \(timeout)")
|
|
301
|
+
var connectionStatus = false
|
|
302
|
+
|
|
303
|
+
if let fula = self.fula {
|
|
304
|
+
let semaphore = DispatchSemaphore(value: 0)
|
|
305
|
+
let queue = DispatchQueue(label: "com.yourapp.checkConnection", attributes: .concurrent)
|
|
306
|
+
|
|
307
|
+
queue.async {
|
|
308
|
+
do {
|
|
309
|
+
NSLog("ReactNative connectToBlox started")
|
|
310
|
+
try fula.connectToBlox()
|
|
311
|
+
connectionStatus = true
|
|
312
|
+
NSLog("ReactNative checkConnectionInternal succeeded")
|
|
313
|
+
semaphore.signal()
|
|
314
|
+
} catch let error {
|
|
315
|
+
NSLog("ReactNative checkConnectionInternal failed with Error: \(error.localizedDescription)")
|
|
316
|
+
semaphore.signal()
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
let timeoutResult = semaphore.wait(timeout: .now() + .seconds(timeout))
|
|
321
|
+
switch timeoutResult {
|
|
322
|
+
case .timedOut:
|
|
323
|
+
NSLog("ReactNative checkConnectionInternal timed out")
|
|
324
|
+
return false
|
|
325
|
+
case .success:
|
|
326
|
+
return connectionStatus
|
|
327
|
+
}
|
|
328
|
+
} else {
|
|
329
|
+
NSLog("ReactNative checkConnectionInternal failed because fula is not initialized")
|
|
330
|
+
return false
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
@objc(checkFailedActions:withTimeout:withResolver:withRejecter:)
|
|
335
|
+
func checkFailedActions(retry: Bool, timeout: Int, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
|
|
336
|
+
do {
|
|
337
|
+
guard let fula = self.fula else {
|
|
338
|
+
throw NSError(domain: "ERR_FULA", code: 1001, userInfo: [NSLocalizedDescriptionKey: "Fula is not initialized"])
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
if !retry {
|
|
342
|
+
NSLog("ReactNative checkFailedActions without retry")
|
|
343
|
+
let failedLinks = try fula.listFailedPushes()
|
|
344
|
+
|
|
345
|
+
let nextFailedLink = try failedLinks.next()
|
|
346
|
+
if nextFailedLink != nil {
|
|
347
|
+
// Assuming nextFailedLink is of type Data; replace `toHex()` with an appropriate method to convert Data to a hex string
|
|
348
|
+
NSLog("ReactNative checkFailedActions found")
|
|
349
|
+
resolve(true)
|
|
350
|
+
} else {
|
|
351
|
+
resolve(false)
|
|
352
|
+
}
|
|
353
|
+
} else {
|
|
354
|
+
NSLog("ReactNative checkFailedActions with retry")
|
|
355
|
+
let retryResults = try retryFailedActionsInternal(timeout: timeout) // Ensure retryFailedActionsInternal accepts a timeout parameter
|
|
356
|
+
resolve(!retryResults)
|
|
357
|
+
}
|
|
358
|
+
} catch let error {
|
|
359
|
+
NSLog("ReactNative checkFailedActions failed with Error: \(error.localizedDescription)")
|
|
360
|
+
reject("ERR_FULA", "CheckFailedActions failed", error)
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
func retryFailedActionsInternal(timeout: Int) throws -> Bool {
|
|
367
|
+
NSLog("ReactNative retryFailedActionsInternal started")
|
|
368
|
+
|
|
369
|
+
guard let fula = self.fula else {
|
|
370
|
+
NSLog("ReactNative retryFailedActionsInternal failed because fula is not initialized")
|
|
371
|
+
return false
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
do {
|
|
375
|
+
let connectionCheck = try checkConnectionInternal(timeout: timeout)
|
|
376
|
+
|
|
377
|
+
if connectionCheck {
|
|
378
|
+
do {
|
|
379
|
+
NSLog("ReactNative retryFailedPushes started")
|
|
380
|
+
try fula.retryFailedPushes()
|
|
381
|
+
NSLog("ReactNative flush started")
|
|
382
|
+
try fula.flush()
|
|
383
|
+
return true
|
|
384
|
+
} catch let error {
|
|
385
|
+
try fula.flush()
|
|
386
|
+
NSLog("ReactNative retryFailedActionsInternal failed with Error: \(error.localizedDescription)")
|
|
387
|
+
return false
|
|
388
|
+
}
|
|
389
|
+
} else {
|
|
390
|
+
NSLog("ReactNative retryFailedActionsInternal failed because blox is offline")
|
|
391
|
+
return false
|
|
392
|
+
}
|
|
393
|
+
} catch let error {
|
|
394
|
+
NSLog("ReactNative retryFailedActionsInternal failed with Error: \(error.localizedDescription)")
|
|
395
|
+
return false
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
func createPeerIdentity(privateKey: Data) throws -> Data {
|
|
400
|
+
let secretKey = try Cryptography.generateKey(privateKey)
|
|
401
|
+
|
|
402
|
+
var encryptedKey: String? = userDataHelper.getValue(FulaModule.PRIVATE_KEY_STORE_ID)
|
|
403
|
+
NSLog("ReactNative createPeerIdentity encryptedKey=\(encryptedKey ?? "nil")")
|
|
404
|
+
if encryptedKey == nil {
|
|
405
|
+
let privateKeyString = String(data: privateKey, encoding: .utf8) ?? ""
|
|
406
|
+
|
|
407
|
+
guard !privateKeyString.isEmpty else {
|
|
408
|
+
throw NSError(domain: "KeyGenerationError", code: -1, userInfo: [NSLocalizedDescriptionKey: "Private key string conversion failed"])
|
|
409
|
+
}
|
|
410
|
+
var error: NSError?
|
|
411
|
+
guard let autoGeneratedIdentity = FulamobileGenerateEd25519KeyFromString(privateKeyString, &error)?.toUint8Array() else {
|
|
412
|
+
throw error ?? NSError(domain: "KeyGenerationError", code: -1, userInfo: nil)
|
|
413
|
+
}
|
|
414
|
+
encryptedKey = try Cryptography.encryptMsg([UInt8](autoGeneratedIdentity), [UInt8](secretKey))
|
|
415
|
+
NSLog("ReactNative createPeerIdentity encryptedKey2=\(encryptedKey)")
|
|
416
|
+
userDataHelper.add(FulaModule.PRIVATE_KEY_STORE_ID, encryptedKey ?? "")
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// Assuming decryptMsg returns Data or throws an error if decryption fails
|
|
420
|
+
guard let encryptedKeyData = encryptedKey, !encryptedKeyData.isEmpty else {
|
|
421
|
+
throw NSError(domain: "DecryptionError", code: -1, userInfo: [NSLocalizedDescriptionKey: "Encrypted key is empty"])
|
|
422
|
+
}
|
|
423
|
+
let decryptedData = try Cryptography.decryptMsg(encryptedKeyData, Array(secretKey))
|
|
424
|
+
let hexString = decryptedData.map { String(format: "%02hhx", $0) }.joined()
|
|
425
|
+
NSLog("ReactNative createPeerIdentity decryptedData=\(hexString)")
|
|
426
|
+
return Data(decryptedData)
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
func decryptLibp2pIdentity(_ encryptedLibp2pId: String, with encryptionSecretKey: Data) throws -> String {
|
|
430
|
+
// Convert Data to [UInt8]
|
|
431
|
+
let secretKeyBytes = [UInt8](encryptionSecretKey)
|
|
432
|
+
|
|
433
|
+
// Attempt decryption
|
|
434
|
+
guard let decryptedBytes = try? Cryptography.decryptMsg(encryptedLibp2pId, secretKeyBytes) else {
|
|
435
|
+
throw NSError(domain: "DecryptionError", code: 1, userInfo: [NSLocalizedDescriptionKey: "Failed to decrypt Libp2p ID"])
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// Assuming decryptedBytes is an array of UInt8
|
|
439
|
+
return String(decoding: decryptedBytes, as: UTF8.self)
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
func createEncryptedLibp2pId(from identity: Data, with encryptionSecretKey: Data) throws -> String {
|
|
443
|
+
var error: NSError?
|
|
444
|
+
guard let autoGeneratedIdentity = FulamobileGenerateEd25519Key(&error) else {
|
|
445
|
+
throw error ?? NSError(domain: "KeyGenerationError", code: -1, userInfo: nil)
|
|
446
|
+
}
|
|
447
|
+
let encryptedLibp2pId = try Cryptography.encryptMsg(Array(autoGeneratedIdentity), Array(encryptionSecretKey))
|
|
448
|
+
userDataHelper.add(FulaModule.PRIVATE_KEY_STORE_ID, encryptedLibp2pId)
|
|
449
|
+
return encryptedLibp2pId
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
func createNewrootCid(identity: Data) throws -> Void {
|
|
453
|
+
let hash32 = identity.sha256()
|
|
454
|
+
NSLog("ReactNative createNewrootCid wnfsKey= \(identity.toHex()) , hash32 = \(hash32.toHex())")
|
|
455
|
+
if (self.fula != nil) {
|
|
456
|
+
NSLog("ReactNative createNewrootCid self.fula not null")
|
|
457
|
+
try self.fula?.flush()
|
|
458
|
+
}
|
|
459
|
+
NSLog("ReactNative fula flushed")
|
|
460
|
+
rootCid = try self.wnfs?.Init(wnfsKey: hash32)
|
|
461
|
+
NSLog("ReactNative privateForest is created: \(rootCid!)")
|
|
462
|
+
wnfsKey = identity
|
|
463
|
+
NSLog("ReactNative rootCid is created: cid= \(rootCid!) wnfs_key= \(wnfsKey!.toHex()), hash32=\(hash32)")
|
|
464
|
+
try encryptAndStoreConfig()
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
func loadWnfs(_ _wnfsKey: Data , _ _rootCid: String) throws {
|
|
468
|
+
NSLog("ReactNative loadWnfs called: _rootCid=\(_rootCid)")
|
|
469
|
+
let hash32 = _wnfsKey.sha256()
|
|
470
|
+
NSLog("ReactNative wnfsKey= \(_wnfsKey.toHex()) ; hash32 = \(hash32.toHex())")
|
|
471
|
+
try self.wnfs?.LoadWithWNFSKey(wnfsKey: hash32, cid: _rootCid)
|
|
472
|
+
NSLog("ReactNative loadWnfs LoadWithWNFSKey")
|
|
473
|
+
rootCid = _rootCid
|
|
474
|
+
wnfsKey = _wnfsKey
|
|
475
|
+
NSLog("ReactNative loadWnfs called: rootCid=\(rootCid)")
|
|
476
|
+
if (self.fula != nil) {
|
|
477
|
+
try self.fula?.flush()
|
|
478
|
+
}
|
|
479
|
+
NSLog("ReactNative loadWnfs completed")
|
|
480
|
+
try encryptAndStoreConfig()
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
func encryptAndStoreConfig() throws {
|
|
485
|
+
do {
|
|
486
|
+
if let identityEncryptedGlobalUnwrapped = identityEncryptedGlobal {
|
|
487
|
+
NSLog("ReactNative encryptAndStoreConfig started")
|
|
488
|
+
|
|
489
|
+
if let rootCidUnwrapped = rootCid, let wnfsKeyUnwrapped = wnfsKey, let secretKeyGlobalUnwrapped = secretKeyGlobal {
|
|
490
|
+
NSLog("ReactNative encryptAndStoreConfig started with rootCid: \(rootCidUnwrapped.toUint8Array()) and wnfsKey:\(wnfsKeyUnwrapped)")
|
|
491
|
+
|
|
492
|
+
let cid_encrypted = try Cryptography.encryptMsg(rootCidUnwrapped.toUint8Array(), secretKeyGlobalUnwrapped)
|
|
493
|
+
NSLog("ReactNative encryptAndStoreConfig cid_encrypted: \(cid_encrypted)")
|
|
494
|
+
|
|
495
|
+
let wnfs_key_encrypted = try Cryptography.encryptMsg(wnfsKeyUnwrapped.toUint8Array(), secretKeyGlobalUnwrapped)
|
|
496
|
+
NSLog("ReactNative encryptAndStoreConfig wnfs_key_encrypted: \(wnfs_key_encrypted)")
|
|
497
|
+
|
|
498
|
+
userDataHelper.add("cid_encrypted_" + identityEncryptedGlobalUnwrapped, cid_encrypted)
|
|
499
|
+
userDataHelper.add("wnfs_key_encrypted_" + identityEncryptedGlobalUnwrapped, wnfs_key_encrypted)
|
|
500
|
+
} else {
|
|
501
|
+
// Handle the case where rootCid, wnfsKey, or secretKeyGlobal is nil
|
|
502
|
+
NSLog("ReactNative encryptAndStoreConfig failed because one of the values is nil")
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
} catch let error {
|
|
506
|
+
NSLog("ReactNative encryptAndStoreConfig failed with Error: \(error.localizedDescription)")
|
|
507
|
+
throw error
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
func logoutInternal(identity: Data, _storePath: String?) throws {
|
|
512
|
+
do {
|
|
513
|
+
if (self.fula != nil) {
|
|
514
|
+
try self.fula?.flush()
|
|
515
|
+
}
|
|
516
|
+
let secretKey = try Cryptography.generateKey(identity)
|
|
517
|
+
let identity_encrypted: String = try Cryptography.encryptMsg(identity.toUint8Array(), [UInt8](secretKey))
|
|
518
|
+
|
|
519
|
+
userDataHelper.remove("cid_encrypted_"+identity_encrypted)
|
|
520
|
+
|
|
521
|
+
//TODO: Should also remove peerid @Mahdi
|
|
522
|
+
|
|
523
|
+
userDataHelper.remove("cid_encrypted_"+identity_encrypted)
|
|
524
|
+
|
|
525
|
+
rootCid = nil
|
|
526
|
+
secretKeyGlobal = nil
|
|
527
|
+
identityEncryptedGlobal = nil
|
|
528
|
+
var storePath = _storePath
|
|
529
|
+
if (storePath == nil || storePath!.isEmpty) {
|
|
530
|
+
storePath = fulaStorePath
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
do{
|
|
534
|
+
try FileManager.default.removeItem(atPath: fulaStorePath)
|
|
535
|
+
}catch let error{
|
|
536
|
+
print("Deleting fula store path", error.localizedDescription)
|
|
537
|
+
throw error
|
|
538
|
+
}
|
|
539
|
+
} catch let error {
|
|
540
|
+
print("ReactNative", "logout internal failed with Error: ", error.localizedDescription)
|
|
541
|
+
throw error
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
func getFulaClient() -> FulamobileClient? {
|
|
546
|
+
return self.fula
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
func newClientInternal(identity: Data, storePath: String?, bloxAddr: String, exchange: String, autoFlush: Bool, useRelay: Bool, refresh: Bool) throws -> Void {
|
|
550
|
+
do {
|
|
551
|
+
NSLog("ReactNative fula newClientInternal refresh=\(refresh)")
|
|
552
|
+
fulaConfig = FulamobileConfig()
|
|
553
|
+
NSLog("ReactNative: cofig is set")
|
|
554
|
+
if (storePath == nil || storePath!.isEmpty) {
|
|
555
|
+
fulaConfig!.storePath = fulaStorePath
|
|
556
|
+
} else {
|
|
557
|
+
fulaConfig!.storePath = storePath!
|
|
558
|
+
}
|
|
559
|
+
NSLog("ReactNative storePath is set: \(fulaConfig!.storePath)")
|
|
560
|
+
|
|
561
|
+
let peerIdentity = try createPeerIdentity(privateKey: identity)
|
|
562
|
+
fulaConfig!.identity = peerIdentity
|
|
563
|
+
NSLog("ReactNative peerIdentity is set: \(fulaConfig!.identity!.toHex())")
|
|
564
|
+
fulaConfig!.bloxAddr = bloxAddr
|
|
565
|
+
NSLog("ReactNative bloxAddr is set: \(fulaConfig!.bloxAddr)")
|
|
566
|
+
fulaConfig!.exchange = exchange
|
|
567
|
+
fulaConfig!.syncWrites = autoFlush
|
|
568
|
+
if (useRelay) {
|
|
569
|
+
fulaConfig!.allowTransientConnection = true
|
|
570
|
+
fulaConfig!.forceReachabilityPrivate = true
|
|
571
|
+
}
|
|
572
|
+
if (self.fula == nil || refresh) {
|
|
573
|
+
NSLog("ReactNative Creating a new Fula instance")
|
|
574
|
+
do {
|
|
575
|
+
try shutdownInternal()
|
|
576
|
+
NSLog("ReactNative Creating a new Fula instance shutdown done")
|
|
577
|
+
var error: NSError?
|
|
578
|
+
let client = FulamobileNewClient(fulaConfig, &error)
|
|
579
|
+
if let error = error {
|
|
580
|
+
throw error
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
self.fula = client
|
|
584
|
+
NSLog("ReactNative FulamobileClient created")
|
|
585
|
+
if (self.fula != nil) {
|
|
586
|
+
NSLog("ReactNative Creating a new Fula instance fula is not null, flushing")
|
|
587
|
+
try self.fula?.flush()
|
|
588
|
+
} else {
|
|
589
|
+
NSLog("** ReactNative Creating a new Fula instance fula failed **")
|
|
590
|
+
}
|
|
591
|
+
} catch let error {
|
|
592
|
+
NSLog("ReactNative Failed to create new Fula instance: \(error.localizedDescription)")
|
|
593
|
+
throw MyError.runtimeError("ReactNative Failed to create new Fula instance")
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
NSLog("ReactNative peerIdentity returned: \(peerIdentity)")
|
|
597
|
+
} catch let error {
|
|
598
|
+
NSLog("ReactNative newclientInternal failed with Error: \(error.localizedDescription)")
|
|
599
|
+
throw error
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
func initInternal(identity: Data, storePath: String, bloxAddr: String, exchange: String, autoFlush: Bool, _rootCid: String, useRelay: Bool, refresh: Bool) throws -> [String] {
|
|
604
|
+
|
|
605
|
+
do {
|
|
606
|
+
os_log("ReactNative: This is an info message.", log: OSLog.viewCycle, type: .info)
|
|
607
|
+
NSLog("ReactNative: This is a simple log message.")
|
|
608
|
+
|
|
609
|
+
NSLog("ReactNative fula initInternal=\(refresh)")
|
|
610
|
+
if (self.fula == nil || refresh) {
|
|
611
|
+
NSLog("ReactNative fula self.fula is null or refresh is set")
|
|
612
|
+
try newClientInternal(identity: identity, storePath: storePath, bloxAddr: bloxAddr, exchange: exchange, autoFlush: autoFlush, useRelay: useRelay, refresh: refresh)
|
|
613
|
+
NSLog("ReactNative fula initialized")
|
|
614
|
+
if (self.fula == nil) {
|
|
615
|
+
NSLog("ReactNative: fula is not initialized")
|
|
616
|
+
}
|
|
617
|
+
guard let fulaId = self.fula?.id_() else {
|
|
618
|
+
NSLog("ReactNative error: fula is not initialized")
|
|
619
|
+
throw MyError.runtimeError("ReactNative: fula client not ready")
|
|
620
|
+
}
|
|
621
|
+
NSLog("ReactNative fula initialized: \(fulaId)")
|
|
622
|
+
}
|
|
623
|
+
if(self.client == nil || self.wnfs == nil || refresh) {
|
|
624
|
+
NSLog("ReactNative fula self.client is null or refresh is set")
|
|
625
|
+
self.client = Client(clientInput: self.fula!)
|
|
626
|
+
self.wnfs = Wnfs(putFn: { cid, data in
|
|
627
|
+
guard let c = self.client else {
|
|
628
|
+
NSLog("ReactNative wnfs put: fula client not ready")
|
|
629
|
+
throw MyError.runtimeError("ReactNative wnfs: fula client not ready")
|
|
630
|
+
}
|
|
631
|
+
try c.put(cid, data)
|
|
632
|
+
}, getFn: { cid in
|
|
633
|
+
guard let c = self.client else {
|
|
634
|
+
NSLog("ReactNative wnfs get: fula client not ready")
|
|
635
|
+
throw MyError.runtimeError("ReactNative wnfs: fula client not ready")
|
|
636
|
+
}
|
|
637
|
+
return try c.get(cid)
|
|
638
|
+
})
|
|
639
|
+
NSLog("ReactNative wnfs initialized")
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
let secretKey = try Cryptography.generateKey(identity)
|
|
643
|
+
let identity_encrypted = try Cryptography.encryptMsg(identity.toUint8Array(), [UInt8](secretKey))
|
|
644
|
+
|
|
645
|
+
identityEncryptedGlobal = identity_encrypted
|
|
646
|
+
secretKeyGlobal = [UInt8](secretKey)
|
|
647
|
+
|
|
648
|
+
if (rootCid == nil || rootCid!.isEmpty) {
|
|
649
|
+
NSLog("ReactNative rootCid is empty.")
|
|
650
|
+
//Load from keystore
|
|
651
|
+
|
|
652
|
+
let cid_encrypted_fetched = userDataHelper.getValue("cid_encrypted_"+identity_encrypted)
|
|
653
|
+
NSLog("ReactNative Here1")
|
|
654
|
+
var cid: Array<UInt8>? = nil
|
|
655
|
+
if(cid_encrypted_fetched != nil && !cid_encrypted_fetched!.isEmpty) {
|
|
656
|
+
NSLog("ReactNative decrypting cid= \(cid_encrypted_fetched!) with secret \(secretKey.toHex())")
|
|
657
|
+
cid = try Cryptography.decryptMsg(cid_encrypted_fetched!, [UInt8](secretKey))
|
|
658
|
+
|
|
659
|
+
}
|
|
660
|
+
NSLog("ReactNative Here2")
|
|
661
|
+
//print("ReactNative", "Attempted to fetch cid from keystore cid="+cid+" & wnfs_key="+wnfs_key)
|
|
662
|
+
if(cid == nil || cid!.isEmpty){
|
|
663
|
+
NSLog("ReactNative cid or wnfs key was not found")
|
|
664
|
+
if(!_rootCid.isEmpty){
|
|
665
|
+
NSLog("ReactNative Re-setting cid from input: \(_rootCid)")
|
|
666
|
+
cid = _rootCid.toUint8Array()
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
}
|
|
670
|
+
if(cid == nil || cid!.isEmpty){
|
|
671
|
+
NSLog("ReactNative Tried to recover cid but was not successful. Creating ones")
|
|
672
|
+
try createNewrootCid(identity: identity)
|
|
673
|
+
} else {
|
|
674
|
+
NSLog("ReactNative Found cid and wnfs key in keychain store")
|
|
675
|
+
NSLog("ReactNative Recovered cid and private ref from keychain store. cid=\(cid!) & wnfs_key=\(identity)")
|
|
676
|
+
try loadWnfs(identity, cid!.toData().toUTF8String()!)
|
|
677
|
+
}
|
|
678
|
+
NSLog("ReactNative creating/reloading rootCid completed")
|
|
679
|
+
|
|
680
|
+
/*
|
|
681
|
+
byte[] testbyte = convertStringToByte("-104,40,24,-93,24,100,24,114,24,111,24,111,24,116,24,-126,24,-126,0,0,24,-128,24,103,24,118,24,101,24,114,24,115,24,105,24,111,24,110,24,101,24,48,24,46,24,49,24,46,24,48,24,105,24,115,24,116,24,114,24,117,24,99,24,116,24,117,24,114,24,101,24,100,24,104,24,97,24,109,24,116")
|
|
682
|
+
long testcodec = 85
|
|
683
|
+
byte[] testputcid = client!.put(testbyte, testcodec)
|
|
684
|
+
print("ReactNative", "client!.put test done"+ Arrays.toString(testputcid))
|
|
685
|
+
byte[] testfetchedcid = convertStringToByte("1,113,18,32,-6,-63,-128,79,-102,-89,57,77,-8,67,-98,8,-81,40,-87,123,122,29,-52,-124,-60,-53,100,105,125,123,-5,-99,41,106,-124,-64")
|
|
686
|
+
byte[] testfetchedbytes = client!.get(testfetchedcid)
|
|
687
|
+
print("ReactNative", "client!.get test done"+ Arrays.toString(testfetchedbytes))
|
|
688
|
+
*/
|
|
689
|
+
|
|
690
|
+
|
|
691
|
+
NSLog("ReactNative rootCid is created: cid=\(self.rootCid!) & wnfs_key=\(self.wnfsKey!.toHex())")
|
|
692
|
+
} else {
|
|
693
|
+
NSLog("ReactNative rootCid existed: cid=\(self.rootCid!) & wnfs_key=\(self.wnfsKey!.toHex())")
|
|
694
|
+
}
|
|
695
|
+
guard let peerId = self.fula?.id_() else {
|
|
696
|
+
NSLog("ReactNative error: fula is not initialized")
|
|
697
|
+
throw MyError.runtimeError("ReactNative: fula client not ready")
|
|
698
|
+
}
|
|
699
|
+
NSLog("ReactNative fula peerId initialized: \(peerId)")
|
|
700
|
+
var obj = [String]()
|
|
701
|
+
obj.append(peerId)
|
|
702
|
+
obj.append(rootCid!)
|
|
703
|
+
obj.append(wnfsKey!.toHex())
|
|
704
|
+
NSLog("ReactNative initInternal is completed successfully")
|
|
705
|
+
if (self.fula != nil) {
|
|
706
|
+
try self.fula?.flush()
|
|
707
|
+
}
|
|
708
|
+
return obj
|
|
709
|
+
} catch let error {
|
|
710
|
+
NSLog("ReactNative init internal failed with Error: \(error.localizedDescription)")
|
|
711
|
+
throw error
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
|
|
716
|
+
@objc(mkdir:withResolver:withRejecter:)
|
|
717
|
+
func mkdir(path: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
718
|
+
NSLog("ReactNative mkdir: path = \(path)")
|
|
719
|
+
do {
|
|
720
|
+
let cid = try self.wnfs?.MkDir(cid: rootCid!, remotePath: path)
|
|
721
|
+
if(cid != nil) {
|
|
722
|
+
rootCid = cid
|
|
723
|
+
try encryptAndStoreConfig()
|
|
724
|
+
if (self.fula != nil) {
|
|
725
|
+
try self.fula?.flush()
|
|
726
|
+
}
|
|
727
|
+
resolve(rootCid)
|
|
728
|
+
} else {
|
|
729
|
+
NSLog("ReactNative mkdir Error: config is nil")
|
|
730
|
+
reject("ERR_WNFS", "Can't make dir", nil)
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
} catch let error{
|
|
734
|
+
print("mkdir", error.localizedDescription)
|
|
735
|
+
reject("ERR_WNFS", "mkdir", error)
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
@objc(writeFile:withLocalFilename:withResolver:withRejecter:)
|
|
740
|
+
func writeFile(fulaTargetFilename: String, localFilename: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
741
|
+
/*
|
|
742
|
+
// reads content of the file form localFilename (should include full absolute path to local file with read permission
|
|
743
|
+
// writes content to the specified location by fulaTargetFilename in Fula filesystem
|
|
744
|
+
// fulaTargetFilename: a string including full path and filename of target file on Fula (e.g. root/pictures/cat.jpg)
|
|
745
|
+
// localFilename: a string containing full path and filename of local file on hte device (e.g /usr/bin/cat.jpg)
|
|
746
|
+
// Returns: new cid of the root after this file is placed in the tree
|
|
747
|
+
*/
|
|
748
|
+
NSLog("ReactNative writeFile to : path = \(fulaTargetFilename) + from: \(localFilename)")
|
|
749
|
+
do {
|
|
750
|
+
let cid = try self.wnfs?.WriteFileFromPath(cid: rootCid!, remotePath: fulaTargetFilename, fileUrl: URL.init(string: localFilename)!)
|
|
751
|
+
if(cid != nil) {
|
|
752
|
+
rootCid = cid
|
|
753
|
+
try encryptAndStoreConfig()
|
|
754
|
+
if (self.fula != nil) {
|
|
755
|
+
try self.fula?.flush()
|
|
756
|
+
}
|
|
757
|
+
resolve(rootCid)
|
|
758
|
+
} else {
|
|
759
|
+
NSLog("ReactNative writeFile Error: config is nil")
|
|
760
|
+
reject("ERR_WNFS", "writeFile Error: config is nil", nil)
|
|
761
|
+
}
|
|
762
|
+
} catch let error {
|
|
763
|
+
print("writeFile", error.localizedDescription)
|
|
764
|
+
reject("ERR_WNFS", "writeFile", error)
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
@objc(writeFileContent:withContentString:withResolver:withRejecter:)
|
|
769
|
+
func writeFileContent(path: String, contentString: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
770
|
+
|
|
771
|
+
NSLog("ReactNative writeFile: contentString = \(contentString)")
|
|
772
|
+
NSLog("ReactNative writeFile: path = \(path)")
|
|
773
|
+
do {
|
|
774
|
+
let content = convertStringToByte(contentString)
|
|
775
|
+
let cid = try self.wnfs?.WriteFile(cid: rootCid!, remotePath: path, data: content.toData())
|
|
776
|
+
rootCid = cid
|
|
777
|
+
try encryptAndStoreConfig()
|
|
778
|
+
if (self.fula != nil) {
|
|
779
|
+
try self.fula?.flush()
|
|
780
|
+
}
|
|
781
|
+
resolve(rootCid)
|
|
782
|
+
} catch let error {
|
|
783
|
+
print("writeFileContent", error.localizedDescription)
|
|
784
|
+
reject("ERR_WNFS", "writeFileContent", error)
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
@objc(ls:withResolver:withRejecter:)
|
|
790
|
+
func ls(path: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
791
|
+
NSLog("ReactNative ls: path = \(path)")
|
|
792
|
+
do {
|
|
793
|
+
let res = try self.wnfs?.Ls(cid: rootCid!, remotePath: path)
|
|
794
|
+
|
|
795
|
+
//JSONArray jsonArray = new JSONArray(res)
|
|
796
|
+
guard let s = res?.toUTF8String() else {
|
|
797
|
+
throw MyError.runtimeError("ReactNative converting bytes to utf8 string")
|
|
798
|
+
}
|
|
799
|
+
NSLog("ReactNative ls: res = \(s)")
|
|
800
|
+
resolve(s)
|
|
801
|
+
} catch let error {
|
|
802
|
+
print("ls", error.localizedDescription)
|
|
803
|
+
reject("ERR_WNFS", "ls", error)
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
@objc(rm:withResolver:withRejecter:)
|
|
809
|
+
func rm(path: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
810
|
+
|
|
811
|
+
print("ReactNative", "rm: path = " + path)
|
|
812
|
+
do {
|
|
813
|
+
let cid = try self.wnfs?.Rm(cid: rootCid!, remotePath: path)
|
|
814
|
+
if(cid != nil) {
|
|
815
|
+
rootCid = cid
|
|
816
|
+
try encryptAndStoreConfig()
|
|
817
|
+
if (self.fula != nil) {
|
|
818
|
+
try self.fula?.flush()
|
|
819
|
+
}
|
|
820
|
+
resolve(rootCid)
|
|
821
|
+
} else {
|
|
822
|
+
print("ReactNative", "rm Error: config is nil")
|
|
823
|
+
reject("ERR_WNFS", "rm Error: config is nil", nil)
|
|
824
|
+
}
|
|
825
|
+
} catch let error {
|
|
826
|
+
print("rm", error.localizedDescription)
|
|
827
|
+
reject("ERR_WNFS", "rm", error)
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
@objc(cp:withTargetPath:withResolver:withRejecter:)
|
|
833
|
+
func cp(sourcePath: String, targetPath: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
834
|
+
|
|
835
|
+
print("ReactNative", "rm: sourcePath = " + sourcePath)
|
|
836
|
+
do {
|
|
837
|
+
let cid = try self.wnfs?.Cp(cid: rootCid!, remotePathFrom: sourcePath, remotePathTo: targetPath)
|
|
838
|
+
if(cid != nil) {
|
|
839
|
+
rootCid = cid
|
|
840
|
+
try encryptAndStoreConfig()
|
|
841
|
+
if (self.fula != nil) {
|
|
842
|
+
try self.fula?.flush()
|
|
843
|
+
}
|
|
844
|
+
resolve(rootCid)
|
|
845
|
+
} else {
|
|
846
|
+
print("ReactNative", "cp Error: config is nil")
|
|
847
|
+
reject("ERR_WNFS", "cp Error: config is nil", nil)
|
|
848
|
+
}
|
|
849
|
+
} catch let error {
|
|
850
|
+
print("cp", error.localizedDescription)
|
|
851
|
+
reject("ERR_WNFS", "cp", error)
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
@objc(mv:withTargetPath:withResolver:withRejecter:)
|
|
857
|
+
func mv(sourcePath: String, targetPath: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
858
|
+
print("ReactNative", "rm: sourcePath = " + sourcePath)
|
|
859
|
+
do {
|
|
860
|
+
let cid = try self.wnfs?.Mv(cid: rootCid!, remotePathFrom: sourcePath, remotePathTo: targetPath)
|
|
861
|
+
if(cid != nil) {
|
|
862
|
+
rootCid = cid
|
|
863
|
+
try encryptAndStoreConfig()
|
|
864
|
+
if (self.fula != nil) {
|
|
865
|
+
try self.fula?.flush()
|
|
866
|
+
}
|
|
867
|
+
resolve(rootCid)
|
|
868
|
+
} else {
|
|
869
|
+
print("ReactNative", "mv Error: config is nil")
|
|
870
|
+
reject("ERR_WNFS", "mv Error: config is nil", nil)
|
|
871
|
+
}
|
|
872
|
+
} catch let error {
|
|
873
|
+
print("mv", error.localizedDescription)
|
|
874
|
+
reject("ERR_WNFS", "mv", error)
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
@objc(readFile:withLocalFilename:withResolver:withRejecter:)
|
|
880
|
+
func readFile(fulaTargetFilename: String, localFilename: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
881
|
+
/*
|
|
882
|
+
// reads content of the file form localFilename (should include full absolute path to local file with read permission
|
|
883
|
+
// writes content to the specified location by fulaTargetFilename in Fula filesystem
|
|
884
|
+
// fulaTargetFilename: a string including full path and filename of target file on Fula (e.g. root/pictures/cat.jpg)
|
|
885
|
+
// localFilename: a string containing full path and filename of local file on hte device (e.g /usr/bin/cat.jpg)
|
|
886
|
+
// Returns: new cid of the root after this file is placed in the tree
|
|
887
|
+
*/
|
|
888
|
+
print("ReactNative", "readFile: fulaTargetFilename = " + fulaTargetFilename)
|
|
889
|
+
do {
|
|
890
|
+
let path = try self.wnfs?.ReadFileToPath(cid: rootCid!, remotePath: fulaTargetFilename, fileUrl: URL.init(string: localFilename)!)
|
|
891
|
+
resolve(path)
|
|
892
|
+
} catch let error {
|
|
893
|
+
print("readFile", error.localizedDescription)
|
|
894
|
+
reject("ERR_WNFS", "readFile", error)
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
@objc(readFileContent:withResolver:withRejecter:)
|
|
900
|
+
func readFileContent(path: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
901
|
+
|
|
902
|
+
print("ReactNative", "readFileContent: path = " + path)
|
|
903
|
+
do {
|
|
904
|
+
// FIXME: dhouldn't we output an NSData object instead?
|
|
905
|
+
let res = try self.wnfs?.ReadFile(cid: rootCid!, remotePath: path)
|
|
906
|
+
guard let resString = res?.toUTF8String() else{
|
|
907
|
+
throw MyError.runtimeError(" ReactNative converting bytes to utf8 string")
|
|
908
|
+
}
|
|
909
|
+
resolve(resString)
|
|
910
|
+
} catch let error {
|
|
911
|
+
print("readFileContent", error.localizedDescription)
|
|
912
|
+
reject("ERR_WNFS", "readFileContent", error)
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
@objc(get:withResolver:withRejecter:)
|
|
918
|
+
func get(keyString: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
919
|
+
|
|
920
|
+
print("ReactNative", "get: keyString = " + keyString)
|
|
921
|
+
do {
|
|
922
|
+
let key: Data = convertStringToByte(keyString).toData()
|
|
923
|
+
let value = try getInternal(key)
|
|
924
|
+
let valueString: String = value.toUTF8String()!
|
|
925
|
+
resolve(valueString)
|
|
926
|
+
} catch let error {
|
|
927
|
+
print("get", error.localizedDescription)
|
|
928
|
+
reject("ERR_FULA", "get", error)
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
func getInternal(_ key: Data) throws -> Data {
|
|
934
|
+
do {
|
|
935
|
+
print("ReactNative", "getInternal: key.toUTF8String() = " , key.toUTF8String()!)
|
|
936
|
+
print("ReactNative", "getInternal: key.toHex().bytes = " , key.toHex())
|
|
937
|
+
let value = try self.fula!.get(key)
|
|
938
|
+
print("ReactNative", "getInternal: value.toHex() = " , value.toHex())
|
|
939
|
+
return value
|
|
940
|
+
} catch let error {
|
|
941
|
+
print("ReactNative", "getInternal: error = " + error.localizedDescription)
|
|
942
|
+
print("getInternal", error.localizedDescription)
|
|
943
|
+
throw error
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
@objc(has:withResolver:withRejecter:)
|
|
948
|
+
func has(keyString: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
949
|
+
|
|
950
|
+
print("ReactNative", "has: keyString = " + keyString)
|
|
951
|
+
do {
|
|
952
|
+
let key: Data = convertStringToByte(keyString).toData()
|
|
953
|
+
let result = try hasInternal(key)
|
|
954
|
+
resolve(result)
|
|
955
|
+
} catch let error {
|
|
956
|
+
print("has", error.localizedDescription)
|
|
957
|
+
reject("ERR_FULA", "has", error)
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
func hasInternal(_ key: Data) throws -> Bool {
|
|
963
|
+
do {
|
|
964
|
+
let ret = UnsafeMutablePointer<ObjCBool>.allocate(capacity: 1)
|
|
965
|
+
try self.fula?.has(key, ret0_: ret)
|
|
966
|
+
let res = ret.pointee.boolValue
|
|
967
|
+
ret.deallocate()
|
|
968
|
+
return res
|
|
969
|
+
} catch let error {
|
|
970
|
+
print("hasInternal", error.localizedDescription)
|
|
971
|
+
throw error
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
func pullInternal(key: Data) throws -> Void {
|
|
976
|
+
do {
|
|
977
|
+
try self.fula!.pull(key)
|
|
978
|
+
} catch let error {
|
|
979
|
+
print("pullInternal", error.localizedDescription)
|
|
980
|
+
throw error
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
@objc(push:withRejecter:)
|
|
985
|
+
func push(resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
986
|
+
print("ReactNative", "push started")
|
|
987
|
+
do {
|
|
988
|
+
try pushInternal(key: convertStringToByte(rootCid!).toData())
|
|
989
|
+
resolve(rootCid)
|
|
990
|
+
} catch let error {
|
|
991
|
+
print("get", error.localizedDescription)
|
|
992
|
+
reject("ERR_FULA", "push", error)
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
func pushInternal(key: Data) throws -> Void {
|
|
997
|
+
do {
|
|
998
|
+
let hasIt = try hasInternal(key)
|
|
999
|
+
if (self.fula != nil && hasIt) {
|
|
1000
|
+
try self.fula?.push(key)
|
|
1001
|
+
try self.fula?.flush()
|
|
1002
|
+
} else {
|
|
1003
|
+
print("ReactNative", "pushInternal error: key wasn't found or fula is not initialized")
|
|
1004
|
+
throw MyError.runtimeError("ReactNative pushInternal error: key wasn't found or fula is not initialized")
|
|
1005
|
+
}
|
|
1006
|
+
} catch let error {
|
|
1007
|
+
print("ReactNative", "pushInternal", error.localizedDescription)
|
|
1008
|
+
throw error
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
// FIXME: unused codecString arg
|
|
1013
|
+
@objc(put:withCodecString:withResolver:withRejecter:)
|
|
1014
|
+
func put(valueString: String, codecString: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
1015
|
+
|
|
1016
|
+
print("ReactNative", "put: codecString = " + codecString)
|
|
1017
|
+
print("ReactNative", "put: valueString = " + valueString)
|
|
1018
|
+
do {
|
|
1019
|
+
//byte[] codec = convertStringToByte(CodecString)
|
|
1020
|
+
let codec = FulaModule.CODEC_DAG_CBOR
|
|
1021
|
+
|
|
1022
|
+
|
|
1023
|
+
print("ReactNative", "put: codec = ", codec)
|
|
1024
|
+
let value = valueString.toData()
|
|
1025
|
+
|
|
1026
|
+
print("ReactNative", "put: value.toHex() = " , value.toHex())
|
|
1027
|
+
let key = try putInternal(value: value, codec: codec)
|
|
1028
|
+
print("ReactNative", "put: key.toHex() = " , key.toUTF8String()!)
|
|
1029
|
+
resolve(key.toUTF8String()!)
|
|
1030
|
+
} catch let error {
|
|
1031
|
+
print("ReactNative", "put: error = ", error.localizedDescription)
|
|
1032
|
+
reject("ERR_FULA", "put", error)
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
// FIXME: unused codec arg
|
|
1038
|
+
func putInternal(value: Data, codec: Int) throws -> Data {
|
|
1039
|
+
do {
|
|
1040
|
+
if(self.fula != nil) {
|
|
1041
|
+
let key: Data = try self.fula!.put(value, codec: Int64(FulaModule.CODEC_DAG_CBOR))
|
|
1042
|
+
try self.fula?.flush()
|
|
1043
|
+
return key
|
|
1044
|
+
} else {
|
|
1045
|
+
print("ReactNative", "putInternal Error: fula is not initialized")
|
|
1046
|
+
throw MyError.runtimeError("ReactNative putInternal Error: fula is not initialized")
|
|
1047
|
+
}
|
|
1048
|
+
} catch let error {
|
|
1049
|
+
print("ReactNative", "putInternal", error.localizedDescription)
|
|
1050
|
+
throw error
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
@objc(setAuth:withAllow:withResolver:withRejecter:)
|
|
1055
|
+
func setAuth(peerIdString: String, allow: Bool, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
1056
|
+
|
|
1057
|
+
print("ReactNative", "setAuth: peerIdString = " + peerIdString)
|
|
1058
|
+
do {
|
|
1059
|
+
if (self.fula != nil && !(self.fula?.id_().isEmpty)! && fulaConfig != nil && !fulaConfig!.bloxAddr.isEmpty) {
|
|
1060
|
+
let bloxAddr = fulaConfig!.bloxAddr
|
|
1061
|
+
print("ReactNative", "setAuth: bloxAddr = '",bloxAddr,"'"," peerIdString = '",peerIdString,"'")
|
|
1062
|
+
let parts = bloxAddr.split(separator: "/").map(String.init)
|
|
1063
|
+
try self.fula?.setAuth(parts.last, subject: peerIdString, allow: allow)
|
|
1064
|
+
resolve(true)
|
|
1065
|
+
} else {
|
|
1066
|
+
print("ReactNative", "setAuth error: fula is not initialized")
|
|
1067
|
+
throw MyError.runtimeError("ReactNative fula is not initialized")
|
|
1068
|
+
}
|
|
1069
|
+
resolve(false)
|
|
1070
|
+
} catch let error {
|
|
1071
|
+
print("get", error.localizedDescription)
|
|
1072
|
+
reject("ERR_FULA", "setAuth", error)
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
@objc(clearCidsFromRecent:withResolver:withRejecter:)
|
|
1078
|
+
func clearCidsFromRecent(cidArray: NSArray, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1079
|
+
DispatchQueue.global(qos: .default).async {
|
|
1080
|
+
do {
|
|
1081
|
+
guard let fulaClient = self.fula else {
|
|
1082
|
+
throw MyError.runtimeError("ReactNative Fula client is not initialized")
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
// Concatenate all CID strings into a single string separated by "|"
|
|
1086
|
+
let concatenatedCids = (cidArray as? [String])?.joined(separator: "|")
|
|
1087
|
+
|
|
1088
|
+
guard let cidsData = concatenatedCids?.data(using: .utf8) else {
|
|
1089
|
+
throw MyError.runtimeError("ReactNative Unable to encode CIDs as data")
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
try fulaClient.clearCids(fromRecent: cidsData)
|
|
1093
|
+
resolve(true)
|
|
1094
|
+
} catch let error {
|
|
1095
|
+
print("ReactNative", "clearCidsFromRecent failed with Error: \(error.localizedDescription)")
|
|
1096
|
+
reject("ERR_FULA_CLEAR_CIDS", "Failed to clear CIDs from recent", error)
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
|
|
1102
|
+
@objc(listRecentCidsAsString:withRejecter:)
|
|
1103
|
+
func listRecentCidsAsString(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1104
|
+
DispatchQueue.global(qos: .default).async {
|
|
1105
|
+
do {
|
|
1106
|
+
guard let fulaClient = self.fula else {
|
|
1107
|
+
throw MyError.runtimeError("ReactNative Fula client is not initialized")
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
let recentLinksIterator = try fulaClient.listRecentCidsAsString()
|
|
1111
|
+
var recentLinksList = [String]()
|
|
1112
|
+
|
|
1113
|
+
while recentLinksIterator.hasNext() {
|
|
1114
|
+
var error: NSError?
|
|
1115
|
+
let nextLink = try recentLinksIterator.next(&error)
|
|
1116
|
+
|
|
1117
|
+
if let error = error {
|
|
1118
|
+
throw error
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
recentLinksList.append(nextLink)
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
if !recentLinksList.isEmpty {
|
|
1125
|
+
// Return the whole list
|
|
1126
|
+
resolve(recentLinksList)
|
|
1127
|
+
} else {
|
|
1128
|
+
resolve(false)
|
|
1129
|
+
}
|
|
1130
|
+
} catch let error {
|
|
1131
|
+
print("ReactNative", "listRecentCidsAsString failed with Error: \(error.localizedDescription)")
|
|
1132
|
+
reject("ERR_FULA_LIST_RECENT_CIDS", "Failed to list recent CIDs as string", error)
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
@objc(listRecentCidsAsStringWithChildren:withRejecter:)
|
|
1138
|
+
func listRecentCidsAsStringWithChildren(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1139
|
+
DispatchQueue.global(qos: .default).async {
|
|
1140
|
+
do {
|
|
1141
|
+
guard let fulaClient = self.fula else {
|
|
1142
|
+
throw MyError.runtimeError("ReactNative Fula client is not initialized")
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
let recentLinksIterator = try fulaClient.listRecentCidsAsStringWithChildren()
|
|
1146
|
+
var recentLinksList = [String]()
|
|
1147
|
+
|
|
1148
|
+
while recentLinksIterator.hasNext() {
|
|
1149
|
+
var error: NSError?
|
|
1150
|
+
let nextLink = try recentLinksIterator.next(&error)
|
|
1151
|
+
|
|
1152
|
+
if let error = error {
|
|
1153
|
+
throw error
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
recentLinksList.append(nextLink)
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
if !recentLinksList.isEmpty {
|
|
1160
|
+
// Return the whole list
|
|
1161
|
+
resolve(recentLinksList)
|
|
1162
|
+
} else {
|
|
1163
|
+
resolve(false)
|
|
1164
|
+
}
|
|
1165
|
+
} catch let error {
|
|
1166
|
+
print("ReactNative", "listRecentCidsAsStringWithChildren failed with Error: \(error.localizedDescription)")
|
|
1167
|
+
reject("ERR_FULA_LIST_RECENT_CIDS_WITH_CHILDREN", "Failed to list recent CIDs as string with children", error)
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
@objc(batchUploadManifest:withPoolId:withReplicationFactor:withResolver:withRejecter:)
|
|
1173
|
+
func batchUploadManifest(cidArray: NSArray, poolIDStr: String, replicationFactorStr: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1174
|
+
DispatchQueue.global(qos: .default).async {
|
|
1175
|
+
do {
|
|
1176
|
+
guard let fulaClient = self.fula else {
|
|
1177
|
+
throw MyError.runtimeError("ReactNative Fula client is not initialized")
|
|
1178
|
+
}
|
|
1179
|
+
guard let poolID = Int64(poolIDStr) else {
|
|
1180
|
+
let error = NSError(domain: "FULAErrorDomain", code: 1001, userInfo: [NSLocalizedDescriptionKey: "Invalid poolID - not a valid number: \(poolIDStr)"])
|
|
1181
|
+
reject("ERR_FULA", "Invalid poolID - not a valid number: \(poolIDStr)", error)
|
|
1182
|
+
return
|
|
1183
|
+
}
|
|
1184
|
+
guard let replicationFactor = Int64(replicationFactorStr) else {
|
|
1185
|
+
let error = NSError(domain: "FULAErrorDomain",
|
|
1186
|
+
code: 1002,
|
|
1187
|
+
userInfo: [NSLocalizedDescriptionKey: "Invalid replicationFactor - not a valid number: \(replicationFactorStr)"])
|
|
1188
|
+
reject("ERR_FULA", "Invalid replicationFactorStr - not a valid number: \(replicationFactorStr)", error)
|
|
1189
|
+
return
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
// Concatenate all CID strings into a single string separated by "|"
|
|
1193
|
+
let concatenatedCids = (cidArray as? [String])?.joined(separator: "|")
|
|
1194
|
+
|
|
1195
|
+
guard let cidsData = concatenatedCids?.data(using: .utf8) else {
|
|
1196
|
+
throw MyError.runtimeError("ReactNative Unable to encode CIDs as data")
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1199
|
+
// Adjusted call to match the expected method signature and argument types
|
|
1200
|
+
try fulaClient.batchUploadManifest(cidsData, poolID: Int(poolID), replicationFactor: Int(replicationFactor))
|
|
1201
|
+
resolve(true)
|
|
1202
|
+
} catch let error {
|
|
1203
|
+
print("ReactNative", "batchUploadManifest failed with Error: \(error.localizedDescription)")
|
|
1204
|
+
reject("ERR_FULA_BATCH_UPLOAD_MANIFEST", "Failed to batch upload CIDs", error)
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
|
|
1210
|
+
|
|
1211
|
+
@objc(shutdown:withRejecter:)
|
|
1212
|
+
func shutdown( resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) {
|
|
1213
|
+
do {
|
|
1214
|
+
try shutdownInternal()
|
|
1215
|
+
resolve(true)
|
|
1216
|
+
} catch let error {
|
|
1217
|
+
NSLog("ReactNative shutdown \(error.localizedDescription)")
|
|
1218
|
+
reject("ERR_FULA", "shutdown", error)
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
@objc
|
|
1224
|
+
func deleteDsLock(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1225
|
+
let lockFilePath = (fulaConfig!.storePath as NSString).appendingPathComponent("LOCK")
|
|
1226
|
+
let fileManager = FileManager.default
|
|
1227
|
+
|
|
1228
|
+
do {
|
|
1229
|
+
if fileManager.fileExists(atPath: lockFilePath) {
|
|
1230
|
+
try fileManager.removeItem(atPath: lockFilePath)
|
|
1231
|
+
NSLog("ReactNative: Lock file deleted successfully.")
|
|
1232
|
+
resolve(true)
|
|
1233
|
+
} else {
|
|
1234
|
+
NSLog("ReactNative: Lock file does not exist.")
|
|
1235
|
+
resolve(false) // Resolve with false if the file doesn't exist
|
|
1236
|
+
}
|
|
1237
|
+
} catch let error as NSError {
|
|
1238
|
+
NSLog("ReactNative: Failed to delete lock file: \(error.localizedDescription)")
|
|
1239
|
+
reject("delete_error", "Failed to delete lock file", error)
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
func shutdownInternal() {
|
|
1244
|
+
NSLog("ReactNative shutdownInternal")
|
|
1245
|
+
if self.fula != nil {
|
|
1246
|
+
NSLog("ReactNative shutdownInternal fula is not null")
|
|
1247
|
+
do {
|
|
1248
|
+
try self.fula?.shutdown()
|
|
1249
|
+
NSLog("ReactNative shutdownInternal fula.shutdown called")
|
|
1250
|
+
} catch {
|
|
1251
|
+
// Handle specific errors if needed or log them
|
|
1252
|
+
NSLog("ReactNative shutdownInternal error: \(error.localizedDescription)")
|
|
1253
|
+
}
|
|
1254
|
+
// Ensure resources are cleaned up regardless of errors
|
|
1255
|
+
self.fula = nil
|
|
1256
|
+
self.client = nil
|
|
1257
|
+
self.wnfs = nil
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1261
|
+
///////////////////////////////////////////////////////////
|
|
1262
|
+
///////////////////////////////////////////////////////////
|
|
1263
|
+
///////////////////////////////////////////////////////////
|
|
1264
|
+
///////////////////////////////////////////////////////////
|
|
1265
|
+
//////////////////////ANYTHING BELOW IS FOR BLOCKCHAIN/////
|
|
1266
|
+
///////////////////////////////////////////////////////////
|
|
1267
|
+
|
|
1268
|
+
@objc(checkAccountExists:withResolver:withRejecter:)
|
|
1269
|
+
func checkAccountExists(accountString: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
1270
|
+
print("ReactNative", "checkAccountExists: accountString = ", accountString)
|
|
1271
|
+
do {
|
|
1272
|
+
let result = try self.fula!.accountExists(accountString)
|
|
1273
|
+
let resultString = result.toUTF8String()!
|
|
1274
|
+
resolve(resultString)
|
|
1275
|
+
} catch let error {
|
|
1276
|
+
print("checkAccountExists", error.localizedDescription)
|
|
1277
|
+
reject("ERR_FULA", "checkAccountExists", error)
|
|
1278
|
+
}
|
|
1279
|
+
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1282
|
+
@objc(accountFund:withResolver:withRejecter:)
|
|
1283
|
+
func accountFund(accountString: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
1284
|
+
print("ReactNative", "accountFund: accountString = ", accountString)
|
|
1285
|
+
do {
|
|
1286
|
+
let result = try self.fula!.accountFund(accountString)
|
|
1287
|
+
let resultString = result.toUTF8String()!
|
|
1288
|
+
resolve(resultString)
|
|
1289
|
+
} catch let error {
|
|
1290
|
+
print("accountFund", error.localizedDescription)
|
|
1291
|
+
reject("ERR_FULA", "accountFund", error)
|
|
1292
|
+
}
|
|
1293
|
+
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
@objc(listPools:withRejecter:)
|
|
1297
|
+
func listPools( resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
1298
|
+
print("ReactNative", "listPools")
|
|
1299
|
+
do {
|
|
1300
|
+
let result = try self.fula!.poolList()
|
|
1301
|
+
let resultString = result.toUTF8String()!
|
|
1302
|
+
resolve(resultString)
|
|
1303
|
+
} catch let error {
|
|
1304
|
+
print("listPools", error.localizedDescription)
|
|
1305
|
+
reject("ERR_FULA", "listPools", error)
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
@objc(listPoolJoinRequests:withResolver:withRejecter:)
|
|
1311
|
+
func listPoolJoinRequests(poolIDStr: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1312
|
+
print("ReactNative", "listPoolJoinRequests: poolIDStr = ", poolIDStr)
|
|
1313
|
+
do {
|
|
1314
|
+
if let poolID = Int64(poolIDStr), let intPoolID = Int(exactly: poolID) {
|
|
1315
|
+
// Conversion to Int successful - use intPoolID
|
|
1316
|
+
let result = try self.fula!.poolRequests(intPoolID)
|
|
1317
|
+
let resultString = result.toUTF8String()!
|
|
1318
|
+
resolve(resultString)
|
|
1319
|
+
} else {
|
|
1320
|
+
// Handle invalid input or Int64 not convertible to Int
|
|
1321
|
+
let error = NSError(domain: "FULAErrorDomain",
|
|
1322
|
+
code: 1003,
|
|
1323
|
+
userInfo: [NSLocalizedDescriptionKey: "Invalid poolIDStr - not a valid number or too large: \(poolIDStr)"])
|
|
1324
|
+
reject("ERR_FULA", "Invalid poolIDStr - not a valid number or too large: \(poolIDStr)", error)
|
|
1325
|
+
}
|
|
1326
|
+
} catch let error {
|
|
1327
|
+
print("listPoolJoinRequests", error.localizedDescription)
|
|
1328
|
+
let nsError = error as NSError
|
|
1329
|
+
reject("ERR_FULA", "Failed listPoolJoinRequests due to error", nsError)
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1333
|
+
@objc(listAvailableReplicationRequests:withResolver:withRejecter:)
|
|
1334
|
+
func listAvailableReplicationRequests(poolIDStr: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1335
|
+
print("ReactNative", "listAvailableReplicationRequests: poolIDStr = ", poolIDStr)
|
|
1336
|
+
do {
|
|
1337
|
+
guard let poolID = Int64(poolIDStr), let intPoolID = Int(exactly: poolID) else {
|
|
1338
|
+
let error = NSError(domain: "FULAErrorDomain",
|
|
1339
|
+
code: 1004, // Use appropriate error code
|
|
1340
|
+
userInfo: [NSLocalizedDescriptionKey: "Invalid poolID - not a valid number: \(poolIDStr)"])
|
|
1341
|
+
reject("ERR_FULA", "Invalid poolID - not a valid number: \(poolIDStr)", error)
|
|
1342
|
+
return
|
|
1343
|
+
}
|
|
1344
|
+
let result = try self.fula!.manifestAvailable(intPoolID)
|
|
1345
|
+
guard let resultString = result.toUTF8String() else {
|
|
1346
|
+
let error = NSError(domain: "FULAErrorDomain",
|
|
1347
|
+
code: 1005, // Use appropriate error code
|
|
1348
|
+
userInfo: [NSLocalizedDescriptionKey: "Failed to convert result to UTF8 String"])
|
|
1349
|
+
reject("ERR_FULA", "Conversion Error", error)
|
|
1350
|
+
return
|
|
1351
|
+
}
|
|
1352
|
+
resolve(resultString)
|
|
1353
|
+
} catch let error as NSError {
|
|
1354
|
+
print("listAvailableReplicationRequests", error.localizedDescription)
|
|
1355
|
+
reject("ERR_FULA", "listAvailableReplicationRequests failed with error: \(error.localizedDescription)", error)
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
|
|
1359
|
+
|
|
1360
|
+
@objc(bloxFreeSpace:withRejecter:)
|
|
1361
|
+
func bloxFreeSpace(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
|
|
1362
|
+
print("ReactNative", "bloxFreeSpace")
|
|
1363
|
+
guard let fulaClient = self.fula else {
|
|
1364
|
+
print("bloxFreeSpace", "fula client is nil")
|
|
1365
|
+
let error = NSError(domain: "FulaModuleError", code: 0, userInfo: [NSLocalizedDescriptionKey: "Fula client is not initialized"])
|
|
1366
|
+
reject("ERR_FULA_NOT_INITIALIZED", "Fula client is not initialized", error)
|
|
1367
|
+
return
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1370
|
+
do {
|
|
1371
|
+
let result = try fulaClient.bloxFreeSpace()
|
|
1372
|
+
guard let resultString = result.toUTF8String() else {
|
|
1373
|
+
let error = NSError(domain: "FulaModuleError", code: 1, userInfo: [NSLocalizedDescriptionKey: "Failed to convert result to String"])
|
|
1374
|
+
reject("ERR_FULA_RESULT_CONVERSION", "Failed to convert result to String", error)
|
|
1375
|
+
return
|
|
1376
|
+
}
|
|
1377
|
+
resolve(resultString)
|
|
1378
|
+
} catch let error {
|
|
1379
|
+
print("bloxFreeSpace", error.localizedDescription)
|
|
1380
|
+
reject("ERR_FULA", "bloxFreeSpace", error)
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1384
|
+
@objc(transferToFula:wallet:chain:withResolver:withRejecter:)
|
|
1385
|
+
func transferToFula(amount: String, wallet: String, chain: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1386
|
+
DispatchQueue.global(qos: .default).async {
|
|
1387
|
+
do {
|
|
1388
|
+
print("ReactNative", "transferToFula called")
|
|
1389
|
+
let result = try self.fula!.transfer(toFula: amount, walletAccount: wallet, chain: chain)
|
|
1390
|
+
let resultString = String(data: result, encoding: .utf8)
|
|
1391
|
+
resolve(resultString)
|
|
1392
|
+
} catch let error {
|
|
1393
|
+
print("ReactNative", "transferToFula failed with Error: \(error.localizedDescription)")
|
|
1394
|
+
reject("ERR_FULA_TRANSFER", "transferToFula failed", error)
|
|
1395
|
+
}
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1398
|
+
|
|
1399
|
+
|
|
1400
|
+
@objc(getAccount:withRejecter:)
|
|
1401
|
+
func getAccount(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1402
|
+
guard let fulaClient = self.fula else {
|
|
1403
|
+
let error = NSError(domain: "FulaModuleError", code: -1, userInfo: [NSLocalizedDescriptionKey: "Fula client is not initialized"])
|
|
1404
|
+
reject("ERR_FULA_NOT_INITIALIZED", "Fula client is not initialized", error)
|
|
1405
|
+
return
|
|
1406
|
+
}
|
|
1407
|
+
|
|
1408
|
+
do {
|
|
1409
|
+
let account = try fulaClient.getAccount()
|
|
1410
|
+
guard let accountString = String(data: account, encoding: .utf8) else {
|
|
1411
|
+
let conversionError = NSError(domain: "FulaModuleError", code: -2, userInfo: [NSLocalizedDescriptionKey: "Unable to convert account data to String"])
|
|
1412
|
+
reject("ERR_FULA_CONVERSION_FAILED", "Unable to convert account data to String", conversionError)
|
|
1413
|
+
return
|
|
1414
|
+
}
|
|
1415
|
+
resolve(accountString)
|
|
1416
|
+
} catch let error {
|
|
1417
|
+
reject("ERR_FULA", "getAccount: \(error.localizedDescription)", error)
|
|
1418
|
+
}
|
|
1419
|
+
}
|
|
1420
|
+
|
|
1421
|
+
@objc(assetsBalance:withAssetId:withClassId:withResolver:withRejecter:)
|
|
1422
|
+
func assetsBalance(account: String, assetId: String, classId: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1423
|
+
guard let assetIdInt = Int(assetId), let classIdInt = Int(classId) else {
|
|
1424
|
+
reject("ERR_FULA", "Invalid assetId or classId", nil)
|
|
1425
|
+
return
|
|
1426
|
+
}
|
|
1427
|
+
|
|
1428
|
+
do {
|
|
1429
|
+
let balance = try self.fula!.assetsBalance(account, assetId: assetIdInt, classId: classIdInt)
|
|
1430
|
+
let balanceString = String(data: balance, encoding: .utf8)
|
|
1431
|
+
resolve(balanceString)
|
|
1432
|
+
} catch let error {
|
|
1433
|
+
reject("ERR_FULA", "assetsBalance: \(error.localizedDescription)", error)
|
|
1434
|
+
}
|
|
1435
|
+
}
|
|
1436
|
+
|
|
1437
|
+
@objc(joinPool:withResolver:withRejecter:)
|
|
1438
|
+
func joinPool(poolID: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1439
|
+
print("ReactNative", "joinPool: poolID = ", poolID)
|
|
1440
|
+
do {
|
|
1441
|
+
guard let poolIdInt = Int(poolID) else {
|
|
1442
|
+
throw NSError(domain: "Invalid poolID", code: 0, userInfo: nil)
|
|
1443
|
+
}
|
|
1444
|
+
let result = try self.fula!.poolJoin(poolIdInt)
|
|
1445
|
+
let resultString = String(data: result, encoding: .utf8)
|
|
1446
|
+
resolve(resultString)
|
|
1447
|
+
} catch let error {
|
|
1448
|
+
reject("ERR_FULA", "joinPool: \(error.localizedDescription)", error)
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1451
|
+
|
|
1452
|
+
@objc(cancelPoolJoin:withResolver:withRejecter:)
|
|
1453
|
+
func cancelPoolJoin(poolID: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1454
|
+
do {
|
|
1455
|
+
guard let poolIdInt = Int(poolID) else {
|
|
1456
|
+
throw NSError(domain: "Invalid poolID", code: 0, userInfo: nil)
|
|
1457
|
+
}
|
|
1458
|
+
let result = try self.fula!.poolCancelJoin(poolIdInt)
|
|
1459
|
+
let resultString = String(data: result, encoding: .utf8)
|
|
1460
|
+
resolve(resultString)
|
|
1461
|
+
} catch let error {
|
|
1462
|
+
reject("ERR_FULA", "cancelPoolJoin: \(error.localizedDescription)", error)
|
|
1463
|
+
}
|
|
1464
|
+
}
|
|
1465
|
+
|
|
1466
|
+
@objc(leavePool:withResolver:withRejecter:)
|
|
1467
|
+
func leavePool(poolID: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1468
|
+
print("ReactNative", "leavePool: poolID = ", poolID)
|
|
1469
|
+
do {
|
|
1470
|
+
guard let poolIdInt = Int(poolID) else {
|
|
1471
|
+
throw NSError(domain: "Invalid poolID", code: 0, userInfo: nil)
|
|
1472
|
+
}
|
|
1473
|
+
let result = try self.fula!.poolLeave(poolIdInt)
|
|
1474
|
+
let resultString = String(data: result, encoding: .utf8)
|
|
1475
|
+
resolve(resultString)
|
|
1476
|
+
} catch let error {
|
|
1477
|
+
reject("ERR_FULA", "leavePool: \(error.localizedDescription)", error)
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
|
|
1481
|
+
|
|
1482
|
+
@objc(eraseBlData:withRejecter:)
|
|
1483
|
+
func eraseBlData(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1484
|
+
do {
|
|
1485
|
+
let result = try self.fula!.eraseBlData()
|
|
1486
|
+
let resultString = String(data: result, encoding: .utf8)
|
|
1487
|
+
resolve(resultString)
|
|
1488
|
+
} catch let error {
|
|
1489
|
+
reject("ERR_FULA", "eraseBlData: \(error.localizedDescription)", error)
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
@objc(reboot:withRejecter:)
|
|
1494
|
+
func reboot(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
|
|
1495
|
+
do {
|
|
1496
|
+
let result = try self.fula!.reboot()
|
|
1497
|
+
let resultString = result.toUTF8String()!
|
|
1498
|
+
resolve(resultString)
|
|
1499
|
+
} catch let error {
|
|
1500
|
+
print("reboot", error.localizedDescription)
|
|
1501
|
+
reject("ERR_FULA", "reboot", error)
|
|
1502
|
+
}
|
|
1503
|
+
}
|
|
1504
|
+
|
|
1505
|
+
@objc(partition:withRejecter:)
|
|
1506
|
+
func partition(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
|
|
1507
|
+
do {
|
|
1508
|
+
let result = try self.fula!.partition()
|
|
1509
|
+
let resultString = result.toUTF8String()!
|
|
1510
|
+
resolve(resultString)
|
|
1511
|
+
} catch let error {
|
|
1512
|
+
print("partition", error.localizedDescription)
|
|
1513
|
+
reject("ERR_FULA", "partition", error)
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1517
|
+
@objc(wifiRemoveall:withRejecter:)
|
|
1518
|
+
func wifiRemoveall(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
|
|
1519
|
+
do {
|
|
1520
|
+
let result = try self.fula!.wifiRemoveall()
|
|
1521
|
+
let resultString = result.toUTF8String()!
|
|
1522
|
+
resolve(resultString)
|
|
1523
|
+
} catch let error {
|
|
1524
|
+
print("wifiRemoveall", error.localizedDescription)
|
|
1525
|
+
reject("ERR_FULA", "wifiRemoveall", error)
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
|
|
1529
|
+
@objc(fetchContainerLogs:withTailCount:withResolver:withRejecter:)
|
|
1530
|
+
func fetchContainerLogs(containerName: String, tailCount: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1531
|
+
do {
|
|
1532
|
+
// Since fetchContainerLogs expects a String for tailCount, pass it directly
|
|
1533
|
+
let result = try self.fula!.fetchContainerLogs(containerName, tailCount: tailCount)
|
|
1534
|
+
guard let resultString = result.toUTF8String() else {
|
|
1535
|
+
// Handle the case where result.toUTF8String() returns nil
|
|
1536
|
+
let error = NSError(domain: "FULAErrorDomain",
|
|
1537
|
+
code: 1007, // Choose a suitable error code
|
|
1538
|
+
userInfo: [NSLocalizedDescriptionKey: "Failed to convert log data to string."])
|
|
1539
|
+
reject("ERR_FULA", "Log Conversion Error", error)
|
|
1540
|
+
return
|
|
1541
|
+
}
|
|
1542
|
+
resolve(resultString)
|
|
1543
|
+
} catch let error as NSError {
|
|
1544
|
+
print("fetchContainerLogs", error.localizedDescription)
|
|
1545
|
+
reject("ERR_FULA", "fetchContainerLogs failed", error)
|
|
1546
|
+
}
|
|
1547
|
+
}
|
|
1548
|
+
@objc(findBestAndTargetInLogs:withTailCount:withResolver:withRejecter:)
|
|
1549
|
+
func findBestAndTargetInLogs(containerName: String, tailCount: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1550
|
+
do {
|
|
1551
|
+
// Since fetchContainerLogs expects a String for tailCount, pass it directly
|
|
1552
|
+
let result = try self.fula!.findBestAndTarget(inLogs: containerName, tailCount: tailCount)
|
|
1553
|
+
guard let resultString = result.toUTF8String() else {
|
|
1554
|
+
// Handle the case where result.toUTF8String() returns nil
|
|
1555
|
+
let error = NSError(domain: "FULAErrorDomain",
|
|
1556
|
+
code: 1007, // Choose a suitable error code
|
|
1557
|
+
userInfo: [NSLocalizedDescriptionKey: "Failed to convert log data to string."])
|
|
1558
|
+
reject("ERR_FULA", "Log Conversion Error", error)
|
|
1559
|
+
return
|
|
1560
|
+
}
|
|
1561
|
+
resolve(resultString)
|
|
1562
|
+
} catch let error as NSError {
|
|
1563
|
+
print("fetchContainerLogs", error.localizedDescription)
|
|
1564
|
+
reject("ERR_FULA", "fetchContainerLogs failed", error)
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1567
|
+
|
|
1568
|
+
|
|
1569
|
+
|
|
1570
|
+
@objc(getFolderSize:withResolver:withRejecter:)
|
|
1571
|
+
func getFolderSize(folderPath: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
|
|
1572
|
+
// Validate the folder path
|
|
1573
|
+
guard !folderPath.isEmpty else {
|
|
1574
|
+
reject("ERR_INVALID_PATH", "The folder path is empty.", nil)
|
|
1575
|
+
return
|
|
1576
|
+
}
|
|
1577
|
+
|
|
1578
|
+
do {
|
|
1579
|
+
// Ensure fula is not nil before calling getFolderSize
|
|
1580
|
+
guard let fula = self.fula else {
|
|
1581
|
+
reject("ERR_FULA", "Fula instance is not initialized.", nil)
|
|
1582
|
+
return
|
|
1583
|
+
}
|
|
1584
|
+
|
|
1585
|
+
// Attempt to get the folder size
|
|
1586
|
+
let result = try fula.getFolderSize(folderPath)
|
|
1587
|
+
|
|
1588
|
+
// Convert the result to a UTF-8 string safely
|
|
1589
|
+
if let resultString = result.toUTF8String() {
|
|
1590
|
+
resolve(resultString)
|
|
1591
|
+
} else {
|
|
1592
|
+
reject("ERR_CONVERSION", "Failed to convert result to UTF-8 string.", nil)
|
|
1593
|
+
}
|
|
1594
|
+
} catch let error {
|
|
1595
|
+
// Log and reject with detailed error information
|
|
1596
|
+
print("getFolderSize error:", error.localizedDescription)
|
|
1597
|
+
reject("ERR_FULA", "Failed to get folder size: \(error.localizedDescription)", error)
|
|
1598
|
+
}
|
|
1599
|
+
}
|
|
1600
|
+
|
|
1601
|
+
@objc
|
|
1602
|
+
func getDatastoreSize(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
|
|
1603
|
+
DispatchQueue.global(qos: .background).async {
|
|
1604
|
+
// Safely unwrap `self.fula` using `guard let`
|
|
1605
|
+
guard let fulaClient = self.fula else {
|
|
1606
|
+
let error = NSError(domain: "FulaModuleError", code: 0, userInfo: [NSLocalizedDescriptionKey: "Fula client is not initialized"])
|
|
1607
|
+
DispatchQueue.main.async {
|
|
1608
|
+
reject("ERR_FULA_NOT_INITIALIZED", "Fula client is not initialized", error)
|
|
1609
|
+
}
|
|
1610
|
+
return
|
|
1611
|
+
}
|
|
1612
|
+
|
|
1613
|
+
do {
|
|
1614
|
+
let result = try fulaClient.getDatastoreSize()
|
|
1615
|
+
let resultString = String(decoding: result, as: UTF8.self)
|
|
1616
|
+
DispatchQueue.main.async {
|
|
1617
|
+
resolve(resultString)
|
|
1618
|
+
}
|
|
1619
|
+
} catch let error {
|
|
1620
|
+
DispatchQueue.main.async {
|
|
1621
|
+
reject("ERR_FULA", "Failed to get datastore size: \(error.localizedDescription)", error)
|
|
1622
|
+
}
|
|
1623
|
+
}
|
|
1624
|
+
}
|
|
1625
|
+
}
|
|
1626
|
+
|
|
1627
|
+
@objc(listPlugins:withRejecter:)
|
|
1628
|
+
func listPlugins(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1629
|
+
DispatchQueue.global(qos: .background).async {
|
|
1630
|
+
do {
|
|
1631
|
+
guard let fula = self.fula else {
|
|
1632
|
+
let error = NSError(domain: "FULAErrorDomain", code: 1001, userInfo: [NSLocalizedDescriptionKey: "Fula instance is not initialized"])
|
|
1633
|
+
DispatchQueue.main.async {
|
|
1634
|
+
reject("ERR_FULA", "Fula not initialized", error)
|
|
1635
|
+
}
|
|
1636
|
+
return
|
|
1637
|
+
}
|
|
1638
|
+
|
|
1639
|
+
let result = try fula.listPlugins()
|
|
1640
|
+
guard let resultString = result.toUTF8String() else {
|
|
1641
|
+
let error = NSError(domain: "FULAErrorDomain", code: 1002, userInfo: [NSLocalizedDescriptionKey: "Failed to convert plugin list to string"])
|
|
1642
|
+
DispatchQueue.main.async {
|
|
1643
|
+
reject("ERR_FULA", "Plugin List Conversion Error", error)
|
|
1644
|
+
}
|
|
1645
|
+
return
|
|
1646
|
+
}
|
|
1647
|
+
|
|
1648
|
+
DispatchQueue.main.async {
|
|
1649
|
+
resolve(resultString)
|
|
1650
|
+
}
|
|
1651
|
+
} catch let error {
|
|
1652
|
+
print("listPlugins", error.localizedDescription)
|
|
1653
|
+
DispatchQueue.main.async {
|
|
1654
|
+
reject("ERR_FULA", "listPlugins failed", error)
|
|
1655
|
+
}
|
|
1656
|
+
}
|
|
1657
|
+
}
|
|
1658
|
+
}
|
|
1659
|
+
|
|
1660
|
+
@objc(listActivePlugins:withRejecter:)
|
|
1661
|
+
func listActivePlugins(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1662
|
+
DispatchQueue.global(qos: .background).async {
|
|
1663
|
+
do {
|
|
1664
|
+
guard let fula = self.fula else {
|
|
1665
|
+
let error = NSError(domain: "FULAErrorDomain", code: 1001, userInfo: [NSLocalizedDescriptionKey: "Fula instance is not initialized"])
|
|
1666
|
+
DispatchQueue.main.async {
|
|
1667
|
+
reject("ERR_FULA", "Fula not initialized", error)
|
|
1668
|
+
}
|
|
1669
|
+
return
|
|
1670
|
+
}
|
|
1671
|
+
|
|
1672
|
+
let result: Data
|
|
1673
|
+
do {
|
|
1674
|
+
result = try fula.listActivePlugins()
|
|
1675
|
+
} catch {
|
|
1676
|
+
print("Error listing active plugins: \(error)")
|
|
1677
|
+
DispatchQueue.main.async {
|
|
1678
|
+
reject("ERR_FULA", "Failed to list active plugins", error)
|
|
1679
|
+
}
|
|
1680
|
+
return
|
|
1681
|
+
}
|
|
1682
|
+
|
|
1683
|
+
guard !result.isEmpty else {
|
|
1684
|
+
let error = NSError(domain: "FULAErrorDomain", code: 1002, userInfo: [NSLocalizedDescriptionKey: "Active plugin list is empty"])
|
|
1685
|
+
DispatchQueue.main.async {
|
|
1686
|
+
reject("ERR_FULA", "Empty Active Plugin List", error)
|
|
1687
|
+
}
|
|
1688
|
+
return
|
|
1689
|
+
}
|
|
1690
|
+
|
|
1691
|
+
guard let resultString = String(data: result, encoding: .utf8) else {
|
|
1692
|
+
let error = NSError(domain: "FULAErrorDomain", code: 1003, userInfo: [NSLocalizedDescriptionKey: "Failed to convert active plugin list to string"])
|
|
1693
|
+
DispatchQueue.main.async {
|
|
1694
|
+
reject("ERR_FULA", "Active Plugin List Conversion Error", error)
|
|
1695
|
+
}
|
|
1696
|
+
return
|
|
1697
|
+
}
|
|
1698
|
+
|
|
1699
|
+
DispatchQueue.main.async {
|
|
1700
|
+
resolve(resultString)
|
|
1701
|
+
}
|
|
1702
|
+
} catch let error {
|
|
1703
|
+
print("listActivePlugins unexpected error:", error.localizedDescription)
|
|
1704
|
+
DispatchQueue.main.async {
|
|
1705
|
+
reject("ERR_FULA", "listActivePlugins failed unexpectedly", error)
|
|
1706
|
+
}
|
|
1707
|
+
}
|
|
1708
|
+
}
|
|
1709
|
+
}
|
|
1710
|
+
|
|
1711
|
+
@objc(installPlugin:withParams:withResolver:withRejecter:)
|
|
1712
|
+
func installPlugin(pluginName: String, params: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1713
|
+
DispatchQueue.global(qos: .background).async {
|
|
1714
|
+
do {
|
|
1715
|
+
guard let fula = self.fula else {
|
|
1716
|
+
let error = NSError(domain: "FULAErrorDomain", code: 1001, userInfo: [NSLocalizedDescriptionKey: "Fula instance is not initialized"])
|
|
1717
|
+
DispatchQueue.main.async {
|
|
1718
|
+
reject("ERR_FULA_NOT_INITIALIZED", "Fula not initialized", error)
|
|
1719
|
+
}
|
|
1720
|
+
return
|
|
1721
|
+
}
|
|
1722
|
+
|
|
1723
|
+
let result = try fula.installPlugin(pluginName, params: params)
|
|
1724
|
+
guard let resultString = result.toUTF8String() else {
|
|
1725
|
+
let error = NSError(domain: "FULAErrorDomain", code: 1002, userInfo: [NSLocalizedDescriptionKey: "Failed to convert install result to string"])
|
|
1726
|
+
DispatchQueue.main.async {
|
|
1727
|
+
reject("ERR_FULA_RESULT_CONVERSION", "Install Result Conversion Error", error)
|
|
1728
|
+
}
|
|
1729
|
+
return
|
|
1730
|
+
}
|
|
1731
|
+
|
|
1732
|
+
DispatchQueue.main.async {
|
|
1733
|
+
resolve(resultString)
|
|
1734
|
+
}
|
|
1735
|
+
} catch let error {
|
|
1736
|
+
print("installPlugin error:", error.localizedDescription)
|
|
1737
|
+
DispatchQueue.main.async {
|
|
1738
|
+
reject("ERR_FULA_INSTALL_PLUGIN", "Failed to install plugin: \(pluginName)", error)
|
|
1739
|
+
}
|
|
1740
|
+
}
|
|
1741
|
+
}
|
|
1742
|
+
}
|
|
1743
|
+
|
|
1744
|
+
@objc(uninstallPlugin:withResolver:withRejecter:)
|
|
1745
|
+
func uninstallPlugin(pluginName: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1746
|
+
DispatchQueue.global(qos: .background).async {
|
|
1747
|
+
do {
|
|
1748
|
+
guard let fula = self.fula else {
|
|
1749
|
+
let error = NSError(domain: "FULAErrorDomain", code: 1001, userInfo: [NSLocalizedDescriptionKey: "Fula instance is not initialized"])
|
|
1750
|
+
DispatchQueue.main.async {
|
|
1751
|
+
reject("ERR_FULA_NOT_INITIALIZED", "Fula not initialized", error)
|
|
1752
|
+
}
|
|
1753
|
+
return
|
|
1754
|
+
}
|
|
1755
|
+
|
|
1756
|
+
let result = try fula.uninstallPlugin(pluginName)
|
|
1757
|
+
guard let resultString = result.toUTF8String() else {
|
|
1758
|
+
let error = NSError(domain: "FULAErrorDomain", code: 1002, userInfo: [NSLocalizedDescriptionKey: "Failed to convert uninstall result to string"])
|
|
1759
|
+
DispatchQueue.main.async {
|
|
1760
|
+
reject("ERR_FULA_RESULT_CONVERSION", "Uninstall Result Conversion Error", error)
|
|
1761
|
+
}
|
|
1762
|
+
return
|
|
1763
|
+
}
|
|
1764
|
+
|
|
1765
|
+
DispatchQueue.main.async {
|
|
1766
|
+
resolve(resultString)
|
|
1767
|
+
}
|
|
1768
|
+
} catch let error {
|
|
1769
|
+
print("uninstallPlugin error:", error.localizedDescription)
|
|
1770
|
+
DispatchQueue.main.async {
|
|
1771
|
+
reject("ERR_FULA_UNINSTALL_PLUGIN", "Failed to uninstall plugin: \(pluginName)", error)
|
|
1772
|
+
}
|
|
1773
|
+
}
|
|
1774
|
+
}
|
|
1775
|
+
}
|
|
1776
|
+
|
|
1777
|
+
@objc(showPluginStatus:withLines:withResolver:withRejecter:)
|
|
1778
|
+
func showPluginStatus(pluginName: String, lines: Int, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1779
|
+
DispatchQueue.global(qos: .background).async {
|
|
1780
|
+
do {
|
|
1781
|
+
guard let fula = self.fula else {
|
|
1782
|
+
let error = NSError(domain: "FULAErrorDomain", code: 1001, userInfo: [NSLocalizedDescriptionKey: "Fula instance is not initialized"])
|
|
1783
|
+
DispatchQueue.main.async {
|
|
1784
|
+
reject("ERR_FULA_NOT_INITIALIZED", "Fula not initialized", error)
|
|
1785
|
+
}
|
|
1786
|
+
return
|
|
1787
|
+
}
|
|
1788
|
+
|
|
1789
|
+
let result: Data
|
|
1790
|
+
do {
|
|
1791
|
+
result = try fula.showPluginStatus(pluginName, lines: lines)
|
|
1792
|
+
} catch {
|
|
1793
|
+
print("Error showing plugin status: \(error)")
|
|
1794
|
+
DispatchQueue.main.async {
|
|
1795
|
+
reject("ERR_FULA_SHOW_PLUGIN_STATUS", "Failed to show plugin status", error)
|
|
1796
|
+
}
|
|
1797
|
+
return
|
|
1798
|
+
}
|
|
1799
|
+
|
|
1800
|
+
guard !result.isEmpty else {
|
|
1801
|
+
let error = NSError(domain: "FULAErrorDomain", code: 1002, userInfo: [NSLocalizedDescriptionKey: "Plugin status result is empty"])
|
|
1802
|
+
DispatchQueue.main.async {
|
|
1803
|
+
reject("ERR_FULA_EMPTY_RESULT", "Empty Plugin Status Result", error)
|
|
1804
|
+
}
|
|
1805
|
+
return
|
|
1806
|
+
}
|
|
1807
|
+
|
|
1808
|
+
guard let resultString = String(data: result, encoding: .utf8) else {
|
|
1809
|
+
let error = NSError(domain: "FULAErrorDomain", code: 1003, userInfo: [NSLocalizedDescriptionKey: "Failed to convert plugin status to string"])
|
|
1810
|
+
DispatchQueue.main.async {
|
|
1811
|
+
reject("ERR_FULA_RESULT_CONVERSION", "Plugin Status Conversion Error", error)
|
|
1812
|
+
}
|
|
1813
|
+
return
|
|
1814
|
+
}
|
|
1815
|
+
|
|
1816
|
+
DispatchQueue.main.async {
|
|
1817
|
+
resolve(resultString)
|
|
1818
|
+
}
|
|
1819
|
+
} catch {
|
|
1820
|
+
print("showPluginStatus unexpected error:", error.localizedDescription)
|
|
1821
|
+
DispatchQueue.main.async {
|
|
1822
|
+
reject("ERR_FULA_SHOW_PLUGIN_STATUS", "showPluginStatus failed unexpectedly", error)
|
|
1823
|
+
}
|
|
1824
|
+
}
|
|
1825
|
+
}
|
|
1826
|
+
}
|
|
1827
|
+
|
|
1828
|
+
@objc(getInstallOutput:withParams:withResolver:withRejecter:)
|
|
1829
|
+
func getInstallOutput(pluginName: String, params: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1830
|
+
DispatchQueue.global(qos: .background).async {
|
|
1831
|
+
do {
|
|
1832
|
+
guard let fula = self.fula else {
|
|
1833
|
+
let error = NSError(domain: "FULAErrorDomain", code: 1001, userInfo: [NSLocalizedDescriptionKey: "Fula instance is not initialized"])
|
|
1834
|
+
DispatchQueue.main.async {
|
|
1835
|
+
reject("ERR_FULA_NOT_INITIALIZED", "Fula not initialized", error)
|
|
1836
|
+
}
|
|
1837
|
+
return
|
|
1838
|
+
}
|
|
1839
|
+
|
|
1840
|
+
let result: Data
|
|
1841
|
+
do {
|
|
1842
|
+
result = try fula.getInstallOutput(pluginName, params: params)
|
|
1843
|
+
} catch {
|
|
1844
|
+
print("Error getting install output: \(error)")
|
|
1845
|
+
DispatchQueue.main.async {
|
|
1846
|
+
reject("ERR_FULA_GET_INSTALL_OUTPUT", "Failed to get install output", error)
|
|
1847
|
+
}
|
|
1848
|
+
return
|
|
1849
|
+
}
|
|
1850
|
+
|
|
1851
|
+
guard !result.isEmpty else {
|
|
1852
|
+
let error = NSError(domain: "FULAErrorDomain", code: 1002, userInfo: [NSLocalizedDescriptionKey: "Install output is empty"])
|
|
1853
|
+
DispatchQueue.main.async {
|
|
1854
|
+
reject("ERR_FULA_EMPTY_RESULT", "Empty Install Output", error)
|
|
1855
|
+
}
|
|
1856
|
+
return
|
|
1857
|
+
}
|
|
1858
|
+
|
|
1859
|
+
guard let resultString = String(data: result, encoding: .utf8) else {
|
|
1860
|
+
let error = NSError(domain: "FULAErrorDomain", code: 1003, userInfo: [NSLocalizedDescriptionKey: "Failed to convert install output to string"])
|
|
1861
|
+
DispatchQueue.main.async {
|
|
1862
|
+
reject("ERR_FULA_RESULT_CONVERSION", "Install Output Conversion Error", error)
|
|
1863
|
+
}
|
|
1864
|
+
return
|
|
1865
|
+
}
|
|
1866
|
+
|
|
1867
|
+
DispatchQueue.main.async {
|
|
1868
|
+
resolve(resultString)
|
|
1869
|
+
}
|
|
1870
|
+
} catch {
|
|
1871
|
+
print("getInstallOutput unexpected error:", error.localizedDescription)
|
|
1872
|
+
DispatchQueue.main.async {
|
|
1873
|
+
reject("ERR_FULA_GET_INSTALL_OUTPUT", "getInstallOutput failed unexpectedly", error)
|
|
1874
|
+
}
|
|
1875
|
+
}
|
|
1876
|
+
}
|
|
1877
|
+
}
|
|
1878
|
+
|
|
1879
|
+
@objc(getInstallStatus:withResolver:withRejecter:)
|
|
1880
|
+
func getInstallStatus(pluginName: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1881
|
+
DispatchQueue.global(qos: .background).async {
|
|
1882
|
+
do {
|
|
1883
|
+
guard let fula = self.fula else {
|
|
1884
|
+
let error = NSError(domain: "FULAErrorDomain", code: 1001, userInfo: [NSLocalizedDescriptionKey: "Fula instance is not initialized"])
|
|
1885
|
+
DispatchQueue.main.async {
|
|
1886
|
+
reject("ERR_FULA_NOT_INITIALIZED", "Fula not initialized", error)
|
|
1887
|
+
}
|
|
1888
|
+
return
|
|
1889
|
+
}
|
|
1890
|
+
|
|
1891
|
+
let result: Data
|
|
1892
|
+
do {
|
|
1893
|
+
result = try fula.getInstallStatus(pluginName)
|
|
1894
|
+
} catch {
|
|
1895
|
+
print("Error getting install status: \(error)")
|
|
1896
|
+
DispatchQueue.main.async {
|
|
1897
|
+
reject("ERR_FULA_GET_INSTALL_STATUS", "Failed to get install status", error)
|
|
1898
|
+
}
|
|
1899
|
+
return
|
|
1900
|
+
}
|
|
1901
|
+
|
|
1902
|
+
guard !result.isEmpty else {
|
|
1903
|
+
let error = NSError(domain: "FULAErrorDomain", code: 1002, userInfo: [NSLocalizedDescriptionKey: "Install status result is empty"])
|
|
1904
|
+
DispatchQueue.main.async {
|
|
1905
|
+
reject("ERR_FULA_EMPTY_RESULT", "Empty Install Status Result", error)
|
|
1906
|
+
}
|
|
1907
|
+
return
|
|
1908
|
+
}
|
|
1909
|
+
|
|
1910
|
+
guard let resultString = String(data: result, encoding: .utf8) else {
|
|
1911
|
+
let error = NSError(domain: "FULAErrorDomain", code: 1003, userInfo: [NSLocalizedDescriptionKey: "Failed to convert install status to string"])
|
|
1912
|
+
DispatchQueue.main.async {
|
|
1913
|
+
reject("ERR_FULA_RESULT_CONVERSION", "Install Status Conversion Error", error)
|
|
1914
|
+
}
|
|
1915
|
+
return
|
|
1916
|
+
}
|
|
1917
|
+
|
|
1918
|
+
DispatchQueue.main.async {
|
|
1919
|
+
resolve(resultString)
|
|
1920
|
+
}
|
|
1921
|
+
} catch {
|
|
1922
|
+
print("getInstallStatus unexpected error:", error.localizedDescription)
|
|
1923
|
+
DispatchQueue.main.async {
|
|
1924
|
+
reject("ERR_FULA_GET_INSTALL_STATUS", "getInstallStatus failed unexpectedly", error)
|
|
1925
|
+
}
|
|
1926
|
+
}
|
|
1927
|
+
}
|
|
1928
|
+
}
|
|
1929
|
+
|
|
1930
|
+
@objc(updatePlugin:withResolver:withRejecter:)
|
|
1931
|
+
func updatePlugin(pluginName: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1932
|
+
DispatchQueue.global(qos: .background).async {
|
|
1933
|
+
do {
|
|
1934
|
+
guard let fula = self.fula else {
|
|
1935
|
+
let error = NSError(domain: "FULAErrorDomain", code: 1001, userInfo: [NSLocalizedDescriptionKey: "Fula instance is not initialized"])
|
|
1936
|
+
DispatchQueue.main.async {
|
|
1937
|
+
reject("ERR_FULA_NOT_INITIALIZED", "Fula not initialized", error)
|
|
1938
|
+
}
|
|
1939
|
+
return
|
|
1940
|
+
}
|
|
1941
|
+
|
|
1942
|
+
let result: Data
|
|
1943
|
+
do {
|
|
1944
|
+
result = try fula.updatePlugin(pluginName)
|
|
1945
|
+
} catch {
|
|
1946
|
+
print("Error updating plugin: \(error)")
|
|
1947
|
+
DispatchQueue.main.async {
|
|
1948
|
+
reject("ERR_FULA_UPDATE_PLUGIN", "Failed to update plugin: \(pluginName)", error)
|
|
1949
|
+
}
|
|
1950
|
+
return
|
|
1951
|
+
}
|
|
1952
|
+
|
|
1953
|
+
guard !result.isEmpty else {
|
|
1954
|
+
let error = NSError(domain: "FULAErrorDomain", code: 1002, userInfo: [NSLocalizedDescriptionKey: "Update plugin result is empty"])
|
|
1955
|
+
DispatchQueue.main.async {
|
|
1956
|
+
reject("ERR_FULA_EMPTY_RESULT", "Empty Update Plugin Result", error)
|
|
1957
|
+
}
|
|
1958
|
+
return
|
|
1959
|
+
}
|
|
1960
|
+
|
|
1961
|
+
guard let resultString = String(data: result, encoding: .utf8) else {
|
|
1962
|
+
let error = NSError(domain: "FULAErrorDomain", code: 1003, userInfo: [NSLocalizedDescriptionKey: "Failed to convert update plugin result to string"])
|
|
1963
|
+
DispatchQueue.main.async {
|
|
1964
|
+
reject("ERR_FULA_RESULT_CONVERSION", "Update Plugin Result Conversion Error", error)
|
|
1965
|
+
}
|
|
1966
|
+
return
|
|
1967
|
+
}
|
|
1968
|
+
|
|
1969
|
+
DispatchQueue.main.async {
|
|
1970
|
+
resolve(resultString)
|
|
1971
|
+
}
|
|
1972
|
+
} catch {
|
|
1973
|
+
print("updatePlugin unexpected error:", error.localizedDescription)
|
|
1974
|
+
DispatchQueue.main.async {
|
|
1975
|
+
reject("ERR_FULA_UPDATE_PLUGIN", "updatePlugin failed unexpectedly", error)
|
|
1976
|
+
}
|
|
1977
|
+
}
|
|
1978
|
+
}
|
|
1979
|
+
}
|
|
1980
|
+
|
|
1981
|
+
@objc(replicateInPool:withAccount:withPoolID:withResolver:withRejecter:)
|
|
1982
|
+
func replicateInPool(cidArray: [String], account: String, poolID: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1983
|
+
DispatchQueue.global(qos: .background).async {
|
|
1984
|
+
do {
|
|
1985
|
+
guard let fula = self.fula else {
|
|
1986
|
+
let error = NSError(domain: "FULAErrorDomain", code: 1001, userInfo: [NSLocalizedDescriptionKey: "Fula instance is not initialized"])
|
|
1987
|
+
DispatchQueue.main.async {
|
|
1988
|
+
reject("ERR_FULA_NOT_INITIALIZED", "Fula not initialized", error)
|
|
1989
|
+
}
|
|
1990
|
+
return
|
|
1991
|
+
}
|
|
1992
|
+
|
|
1993
|
+
guard let poolIDLong = Int64(poolID) else {
|
|
1994
|
+
let error = NSError(domain: "FULAErrorDomain", code: 1002, userInfo: [NSLocalizedDescriptionKey: "Invalid poolID"])
|
|
1995
|
+
DispatchQueue.main.async {
|
|
1996
|
+
reject("ERR_FULA_INVALID_POOL_ID", "Invalid poolID", error)
|
|
1997
|
+
}
|
|
1998
|
+
return
|
|
1999
|
+
}
|
|
2000
|
+
|
|
2001
|
+
guard let poolIDInt = Int(exactly: poolIDLong) else {
|
|
2002
|
+
let error = NSError(domain: "FULAErrorDomain", code: 1003, userInfo: [NSLocalizedDescriptionKey: "PoolID is too large for Int"])
|
|
2003
|
+
DispatchQueue.main.async {
|
|
2004
|
+
reject("ERR_FULA_POOL_ID_OVERFLOW", "PoolID is too large", error)
|
|
2005
|
+
}
|
|
2006
|
+
return
|
|
2007
|
+
}
|
|
2008
|
+
|
|
2009
|
+
let cidString = cidArray.joined(separator: "|")
|
|
2010
|
+
guard let cidsBytes = cidString.data(using: .utf8) else {
|
|
2011
|
+
let error = NSError(domain: "FULAErrorDomain", code: 1004, userInfo: [NSLocalizedDescriptionKey: "Failed to encode CIDs as data"])
|
|
2012
|
+
DispatchQueue.main.async {
|
|
2013
|
+
reject("ERR_FULA_CID_ENCODING", "Failed to encode CIDs", error)
|
|
2014
|
+
}
|
|
2015
|
+
return
|
|
2016
|
+
}
|
|
2017
|
+
|
|
2018
|
+
let result: Data
|
|
2019
|
+
do {
|
|
2020
|
+
if let replicationResult = try fula.replicate(inPool: cidsBytes, account: account, poolID: poolIDInt) {
|
|
2021
|
+
result = replicationResult
|
|
2022
|
+
} else {
|
|
2023
|
+
throw NSError(domain: "FULAErrorDomain", code: 1007, userInfo: [NSLocalizedDescriptionKey: "Replication result is nil"])
|
|
2024
|
+
}
|
|
2025
|
+
} catch {
|
|
2026
|
+
print("Error replicating in pool: \(error)")
|
|
2027
|
+
DispatchQueue.main.async {
|
|
2028
|
+
reject("ERR_FULA_REPLICATION", "Failed to replicate in pool", error)
|
|
2029
|
+
}
|
|
2030
|
+
return
|
|
2031
|
+
}
|
|
2032
|
+
|
|
2033
|
+
guard !result.isEmpty else {
|
|
2034
|
+
let error = NSError(domain: "FULAErrorDomain", code: 1005, userInfo: [NSLocalizedDescriptionKey: "Replication result is empty"])
|
|
2035
|
+
DispatchQueue.main.async {
|
|
2036
|
+
reject("ERR_FULA_EMPTY_RESULT", "Empty replication result", error)
|
|
2037
|
+
}
|
|
2038
|
+
return
|
|
2039
|
+
}
|
|
2040
|
+
|
|
2041
|
+
guard let resultString = String(data: result, encoding: .utf8) else {
|
|
2042
|
+
let error = NSError(domain: "FULAErrorDomain", code: 1006, userInfo: [NSLocalizedDescriptionKey: "Failed to decode result data to string"])
|
|
2043
|
+
DispatchQueue.main.async {
|
|
2044
|
+
reject("ERR_FULA_RESULT_DECODING", "Failed to decode result", error)
|
|
2045
|
+
}
|
|
2046
|
+
return
|
|
2047
|
+
}
|
|
2048
|
+
|
|
2049
|
+
DispatchQueue.main.async {
|
|
2050
|
+
resolve(resultString)
|
|
2051
|
+
}
|
|
2052
|
+
} catch {
|
|
2053
|
+
print("replicateInPool unexpected error:", error.localizedDescription)
|
|
2054
|
+
DispatchQueue.main.async {
|
|
2055
|
+
reject("ERR_FULA_REPLICATE_IN_POOL", "replicateInPool failed unexpectedly", error)
|
|
2056
|
+
}
|
|
2057
|
+
}
|
|
2058
|
+
}
|
|
2059
|
+
}
|
|
2060
|
+
|
|
2061
|
+
// AI Chat methods
|
|
2062
|
+
|
|
2063
|
+
@objc(chatWithAI:withUserMessage:withResolver:withRejecter:)
|
|
2064
|
+
func chatWithAI(aiModel: String, userMessage: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
|
|
2065
|
+
NSLog("ReactNative chatWithAI: aiModel = \(aiModel), userMessage = \(userMessage)")
|
|
2066
|
+
DispatchQueue.global(qos: .default).async {
|
|
2067
|
+
do {
|
|
2068
|
+
guard let fula = self.fula else {
|
|
2069
|
+
throw MyError.runtimeError("ReactNative Fula client is not initialized")
|
|
2070
|
+
}
|
|
2071
|
+
|
|
2072
|
+
// Call the Go Mobile method, which returns Data
|
|
2073
|
+
let streamIDData = try fula.chatWithAI(aiModel, userMessage: userMessage)
|
|
2074
|
+
|
|
2075
|
+
// Convert Data to String (assuming UTF-8 encoding)
|
|
2076
|
+
guard let streamID = String(data: streamIDData, encoding: .utf8) else {
|
|
2077
|
+
throw MyError.runtimeError("Failed to convert stream ID to string")
|
|
2078
|
+
}
|
|
2079
|
+
|
|
2080
|
+
// Resolve the promise with the stream ID
|
|
2081
|
+
DispatchQueue.main.async {
|
|
2082
|
+
resolve(streamID)
|
|
2083
|
+
}
|
|
2084
|
+
} catch let error {
|
|
2085
|
+
NSLog("ReactNative ERROR in chatWithAI: \(error.localizedDescription)")
|
|
2086
|
+
DispatchQueue.main.async {
|
|
2087
|
+
reject("ERR_CHAT_WITH_AI", "Chat with AI failed", error)
|
|
2088
|
+
}
|
|
2089
|
+
}
|
|
2090
|
+
}
|
|
2091
|
+
}
|
|
2092
|
+
|
|
2093
|
+
@objc(getChatChunk:withResolver:withRejecter:)
|
|
2094
|
+
func getChatChunk(streamID: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
|
|
2095
|
+
NSLog("ReactNative getChatChunk: streamID = \(streamID)")
|
|
2096
|
+
DispatchQueue.global(qos: .default).async {
|
|
2097
|
+
do {
|
|
2098
|
+
guard let fula = self.fula else {
|
|
2099
|
+
throw MyError.runtimeError("ReactNative Fula client is not initialized")
|
|
2100
|
+
}
|
|
2101
|
+
|
|
2102
|
+
// Call the Go Mobile method, which returns a String
|
|
2103
|
+
let chunk = try fula.getChatChunk(streamID)
|
|
2104
|
+
|
|
2105
|
+
// Handle null or empty response
|
|
2106
|
+
if chunk.isEmpty {
|
|
2107
|
+
NSLog("ReactNative getChatChunk: No data received for streamID = \(streamID)")
|
|
2108
|
+
DispatchQueue.main.async {
|
|
2109
|
+
resolve("") // Resolve with an empty string
|
|
2110
|
+
}
|
|
2111
|
+
return
|
|
2112
|
+
}
|
|
2113
|
+
|
|
2114
|
+
// Resolve the promise with the chunk of data
|
|
2115
|
+
NSLog("ReactNative getChatChunk: Successfully received chunk for streamID = \(streamID)")
|
|
2116
|
+
DispatchQueue.main.async {
|
|
2117
|
+
resolve(chunk)
|
|
2118
|
+
}
|
|
2119
|
+
} catch let error {
|
|
2120
|
+
// Log and reject the promise with the error
|
|
2121
|
+
NSLog("ReactNative ERROR in getChatChunk: \(error.localizedDescription)")
|
|
2122
|
+
DispatchQueue.main.async {
|
|
2123
|
+
reject("ERR_GET_CHAT_CHUNK", "Get chat chunk failed", error)
|
|
2124
|
+
}
|
|
2125
|
+
}
|
|
2126
|
+
}
|
|
2127
|
+
}
|
|
2128
|
+
|
|
2129
|
+
@objc(streamChunks:withResolver:withRejecter:)
|
|
2130
|
+
func streamChunks(streamID: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
|
|
2131
|
+
if streamID.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
|
2132
|
+
reject("INVALID_ARGUMENT", "streamID cannot be null or empty", nil)
|
|
2133
|
+
return
|
|
2134
|
+
}
|
|
2135
|
+
|
|
2136
|
+
DispatchQueue.global(qos: .default).async {
|
|
2137
|
+
do {
|
|
2138
|
+
guard let fula = self.fula else {
|
|
2139
|
+
throw MyError.runtimeError("ReactNative Fula client is not initialized")
|
|
2140
|
+
}
|
|
2141
|
+
|
|
2142
|
+
guard let iterator = try fula.getStreamIterator(streamID) else {
|
|
2143
|
+
throw MyError.runtimeError("Failed to create StreamIterator")
|
|
2144
|
+
}
|
|
2145
|
+
|
|
2146
|
+
// Start listening for chunks on the main thread
|
|
2147
|
+
DispatchQueue.main.async {
|
|
2148
|
+
self.pollIterator(iterator: iterator, resolve: resolve, reject: reject)
|
|
2149
|
+
}
|
|
2150
|
+
} catch let error {
|
|
2151
|
+
NSLog("ReactNative ERROR in streamChunks: \(error.localizedDescription)")
|
|
2152
|
+
DispatchQueue.main.async {
|
|
2153
|
+
reject("STREAM_ERROR", "Stream error", error)
|
|
2154
|
+
}
|
|
2155
|
+
}
|
|
2156
|
+
}
|
|
2157
|
+
}
|
|
2158
|
+
|
|
2159
|
+
private func pollIterator(iterator: FulamobileStreamIterator, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
2160
|
+
do {
|
|
2161
|
+
let chunk = try iterator.next()
|
|
2162
|
+
if !chunk.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
|
2163
|
+
self.emitEvent(eventName: "onChunkReceived", data: chunk)
|
|
2164
|
+
}
|
|
2165
|
+
|
|
2166
|
+
if iterator.isComplete() {
|
|
2167
|
+
self.emitEvent(eventName: "onStreamingCompleted", data: nil)
|
|
2168
|
+
resolve(nil)
|
|
2169
|
+
} else {
|
|
2170
|
+
// Schedule another poll with a short delay
|
|
2171
|
+
DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) { // 50ms delay for better responsiveness
|
|
2172
|
+
self.pollIterator(iterator: iterator, resolve: resolve, reject: reject)
|
|
2173
|
+
}
|
|
2174
|
+
}
|
|
2175
|
+
} catch let error {
|
|
2176
|
+
let errorMessage = error.localizedDescription
|
|
2177
|
+
if errorMessage.contains("EOF") {
|
|
2178
|
+
self.emitEvent(eventName: "onStreamingCompleted", data: nil)
|
|
2179
|
+
resolve(nil)
|
|
2180
|
+
} else if errorMessage.contains("timeout") {
|
|
2181
|
+
// Retry on timeout
|
|
2182
|
+
DispatchQueue.main.async {
|
|
2183
|
+
self.pollIterator(iterator: iterator, resolve: resolve, reject: reject)
|
|
2184
|
+
}
|
|
2185
|
+
} else {
|
|
2186
|
+
self.emitEvent(eventName: "onStreamError", data: errorMessage)
|
|
2187
|
+
reject("STREAM_ERROR", errorMessage, error)
|
|
2188
|
+
}
|
|
2189
|
+
}
|
|
2190
|
+
}
|
|
2191
|
+
|
|
2192
|
+
private func emitEvent(eventName: String, data: String?) {
|
|
2193
|
+
do {
|
|
2194
|
+
guard let eventEmitter = RCTBridge.current()?.eventDispatcher() else {
|
|
2195
|
+
NSLog("ReactNative ERROR: Could not get event dispatcher")
|
|
2196
|
+
return
|
|
2197
|
+
}
|
|
2198
|
+
|
|
2199
|
+
eventEmitter.sendAppEvent(withName: eventName, body: data)
|
|
2200
|
+
} catch {
|
|
2201
|
+
NSLog("ReactNative Error emitting event: \(eventName), \(error.localizedDescription)")
|
|
2202
|
+
}
|
|
2203
|
+
}
|
|
2204
|
+
|
|
2205
|
+
}
|
|
2206
|
+
|
|
2207
|
+
|