MongoView/MongoView/MongoEvaluator.swift

85 lines
2.6 KiB
Swift

//
// MongoEvaluator.swift
// MongoView
//
// Created by Shadowfacts on 1/12/20.
// Copyright © 2020 Shadowfacts. All rights reserved.
//
import Foundation
import JavaScriptCore
import MongoSwift
struct MongoEvaluator {
static let context: JSContext = {
let context = JSContext()!
let date: @convention(block) (JSValue) -> Dictionary<String, Any> = { (input) in
["$date": input]
}
let functions: [NSString: @convention(block) (JSValue) -> Dictionary<String, Any>] = [
"ObjectId": { (input) in
["$oid": input]
},
"NumberLong": { (input) in
["$numberLong": input]
},
"NumberInt": { (input) in
["$numberInt": input]
},
"NumberDecimal": { (input) in
["$numberDecimal": input]
},
"Date": date,
"ISODate": date,
]
functions.forEach { (key, value) in
context.setObject(value, forKeyedSubscript: key)
}
let dbRef: @convention(block) (String, String) -> Dictionary<String, Any> = { (ref, id) in
["$ref": ref, "$id": ["$oid": id]]
}
context.setObject(dbRef, forKeyedSubscript: "DBRef" as NSString)
return context
}()
static func parse(shellJSON: String) -> Document? {
guard !shellJSON.isEmpty,
let result = context.evaluateScript("JSON.stringify(\(shellJSON))") else {
return nil
}
do {
return try Document(fromJSON: result.toString())
} catch {
print("Unable to parse Document: \(error)")
return nil
}
}
static func eval(command: String, connectingTo connStr: String) -> [Document] {
print("Running command \"\(command)\" against \(connStr)")
let mongoOutputPipe = Pipe()
let mongoProcess = Process()
mongoProcess.launchPath = "/usr/local/bin/mongo"
mongoProcess.arguments = [connStr, "--quiet", "--norc", "--eval", command]
mongoProcess.standardOutput = mongoOutputPipe
mongoProcess.launch()
let mongoOutputHandle = mongoOutputPipe.fileHandleForReading
var strs = [String]()
var data: Data!
repeat {
data = mongoOutputHandle.availableData
strs.append(String(data: data, encoding: .utf8)!)
} while (data.count > 0)
mongoOutputHandle.closeFile()
let lines = strs.joined(separator: "").components(separatedBy: "\n")
return lines.compactMap(parse(shellJSON:))
}
}