1 import Foundation 2 3 class EXDevLauncherRemoteLogsManager { 4 private var batch: [String] = [] 5 private let url: URL 6 7 init(withUrl url: URL) { 8 self.url = url 9 } 10 deferErrornull11 func deferError(exception: NSException) { 12 batch.append("\(exception.name.rawValue): \(exception.reason ?? exception.description)") 13 batch.append(" \(exception.callStackSymbols.joined(separator: "\n "))") 14 } 15 deferErrornull16 func deferError(message: String) { 17 batch.append(message) 18 } 19 sendSyncnull20 func sendSync() { 21 // message format comes from 22 // https://github.com/facebook/react-native/blob/0.69-stable/Libraries/Utilities/HMRClient.js#L119-L134 23 let messageJson = [ 24 "type": "log", 25 "level": "error", 26 "mode": "BRIDGE", 27 // `data` is an array whose members are simply concatenated with a space before printing to 28 // the console, so we join messages with a newline and send an array consisting of just a 29 // single item. 30 "data": [batch.joined(separator: "\n")] 31 ] as [String: Any] 32 guard let data = try? JSONSerialization.data(withJSONObject: messageJson, options: []) else { 33 batch.removeAll() 34 return 35 } 36 37 batch.removeAll() 38 39 if #available(iOS 13.0, *) { 40 let group = DispatchGroup() 41 group.enter() 42 43 let task = URLSession.shared.webSocketTask(with: self.url) 44 task.resume() 45 46 guard let dataString = String(data: data, encoding: .utf8) else { 47 group.leave() 48 return 49 } 50 let message = URLSessionWebSocketTask.Message.string(dataString) 51 task.send(message) { _ in 52 group.leave() 53 } 54 _ = group.wait(timeout: DispatchTime.now() + .seconds(2)) 55 } 56 } 57 } 58