Compare commits

...

3 Commits

5 changed files with 31 additions and 47 deletions

View File

@ -7,63 +7,37 @@
// //
import Foundation import Foundation
import JavaScriptCore
import MongoSwift import MongoSwift
struct MongoEvaluator { struct MongoEvaluator {
static let context: JSContext = { static let decoder = BSONDecoder()
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? { static func parse(extendedJSON: String) -> BSON? {
guard !shellJSON.isEmpty, guard !extendedJSON.isEmpty else {
let result = context.evaluateScript("JSON.stringify(\(shellJSON))") else { return nil
return nil
} }
do { do {
return try Document(fromJSON: result.toString()) return try decoder.decode(BSON.self, from: extendedJSON)
} catch { } catch {
print("Unable to parse Document: \(error)") print("Unable to parse BSON: \(error)")
return nil return nil
} }
} }
static func eval(command: String, connectingTo connStr: String) -> [Document] { static func eval(command: String, connectingTo connStr: String) -> [BSON] {
let realCommand = """
Object.prototype.printExtJSON = function() { print(JSON.stringify(this)); };
Array.prototype.printExtJSON = function() { this.map(JSON.stringify).forEach(it => print(it)); };
\(command).printExtJSON()
"""
print("Running command \"\(command)\" against \(connStr)") print("Running command \"\(command)\" against \(connStr)")
let mongoOutputPipe = Pipe() let mongoOutputPipe = Pipe()
let mongoProcess = Process() let mongoProcess = Process()
mongoProcess.launchPath = "/usr/local/bin/mongo" mongoProcess.launchPath = "/usr/local/bin/mongo"
mongoProcess.arguments = [connStr, "--quiet", "--norc", "--eval", command] mongoProcess.arguments = [connStr, "--quiet", "--norc", "--eval", realCommand]
mongoProcess.standardOutput = mongoOutputPipe mongoProcess.standardOutput = mongoOutputPipe
mongoProcess.launch() mongoProcess.launch()
@ -78,7 +52,7 @@ struct MongoEvaluator {
mongoOutputHandle.closeFile() mongoOutputHandle.closeFile()
let lines = strs.joined(separator: "").components(separatedBy: "\n") let lines = strs.joined(separator: "").components(separatedBy: "\n")
return lines.compactMap(parse(shellJSON:)) return lines.compactMap(parse(extendedJSON:))
} }
} }

View File

@ -37,8 +37,15 @@ class Node {
} }
init(key: Key? = nil, value: BSON) { init(key: Key? = nil, value: BSON) {
self.key = key
self.value = value self.value = value
if key == nil,
case let .document(doc) = value,
case let .objectId(id) = doc["_id"] {
self.key = .objectId(id)
} else {
self.key = key
}
} }
convenience init(document: Document) { convenience init(document: Document) {

View File

@ -47,9 +47,11 @@ class DatabaseViewController: NSViewController {
super.viewDidLoad() super.viewDidLoad()
mongoController.client.listDatabaseNames().flatMap { (databaseNames) -> EventLoopFuture<[DatabaseCollections]> in mongoController.client.listDatabaseNames().flatMap { (databaseNames) -> EventLoopFuture<[DatabaseCollections]> in
let futures = databaseNames.map { (name) in let futures = databaseNames.map { (name: String) -> EventLoopFuture<DatabaseCollections> in
self.mongoController.client.db(name).listCollectionNames().map { (collectionNames) in let db = self.mongoController.client.db(name)
DatabaseCollections(database: name, collections: collectionNames) return db.listCollectionNames().map { (collectionNames: [String]) -> DatabaseCollections in
let sortedNames = collectionNames.sorted()
return DatabaseCollections(database: name, collections: sortedNames)
} }
} }
return EventLoopFuture.whenAllSucceed(futures, on: futures.first!.eventLoop) return EventLoopFuture.whenAllSucceed(futures, on: futures.first!.eventLoop)
@ -58,7 +60,8 @@ class DatabaseViewController: NSViewController {
switch res { switch res {
case let .success(databaseCollections): case let .success(databaseCollections):
self.databaseCollections = databaseCollections let sortedCollections = databaseCollections.sorted(by: { $0.database < $1.database })
self.databaseCollections = sortedCollections
DispatchQueue.main.async { DispatchQueue.main.async {
self.collectionsOutlineView.reloadData() self.collectionsOutlineView.reloadData()
} }

View File

@ -20,7 +20,7 @@ class QueryViewController: NSViewController {
let collection: DatabaseCollection let collection: DatabaseCollection
var defaultQuery: String { var defaultQuery: String {
"db.getCollection('\(collection.name)').find({})" "db.getCollection('\(collection.name)').find({}).toArray()"
} }
var hasQueryChanged: Bool { var hasQueryChanged: Bool {

View File

@ -990,7 +990,7 @@
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
</scroller> </scroller>
</scrollView> </scrollView>
<scrollView fixedFrame="YES" autohidesScrollers="YES" horizontalLineScroll="19" horizontalPageScroll="10" verticalLineScroll="19" verticalPageScroll="10" usesPredominantAxisScrolling="NO" id="tUs-K7-aZX"> <scrollView fixedFrame="YES" horizontalLineScroll="19" horizontalPageScroll="10" verticalLineScroll="19" verticalPageScroll="10" usesPredominantAxisScrolling="NO" id="tUs-K7-aZX">
<rect key="frame" x="0.0" y="96" width="741" height="371"/> <rect key="frame" x="0.0" y="96" width="741" height="371"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<clipView key="contentView" id="eia-Pq-LIB"> <clipView key="contentView" id="eia-Pq-LIB">