Compare commits
3 Commits
954b0bc8a6
...
624befaec2
Author | SHA1 | Date |
---|---|---|
Shadowfacts | 624befaec2 | |
Shadowfacts | 01418e44ad | |
Shadowfacts | e507817b84 |
|
@ -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:))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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">
|
||||||
|
|
Loading…
Reference in New Issue