Browse Source

Initial commit

master
Shadowfacts 10 months ago
commit
8eee8767d1
Signed by: Shadowfacts <me@shadowfacts.net> GPG Key ID: 94A5AB95422746E5

+ 77
- 0
.gitignore View File

@@ -0,0 +1,77 @@
1
+.DS_Store
2
+
3
+### Swift ###
4
+# Xcode
5
+#
6
+# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
7
+
8
+## Build generated
9
+build/
10
+DerivedData/
11
+
12
+## Various settings
13
+*.pbxuser
14
+!default.pbxuser
15
+*.mode1v3
16
+!default.mode1v3
17
+*.mode2v3
18
+!default.mode2v3
19
+*.perspectivev3
20
+!default.perspectivev3
21
+xcuserdata/
22
+
23
+## Other
24
+*.moved-aside
25
+*.xccheckout
26
+*.xcscmblueprint
27
+
28
+## Obj-C/Swift specific
29
+*.hmap
30
+*.ipa
31
+*.dSYM.zip
32
+*.dSYM
33
+
34
+## Playgrounds
35
+timeline.xctimeline
36
+playground.xcworkspace
37
+
38
+# Swift Package Manager
39
+#
40
+# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
41
+# Packages/
42
+# Package.pins
43
+.build/
44
+
45
+# CocoaPods - Refactored to standalone file
46
+
47
+# Carthage - Refactored to standalone file
48
+
49
+# fastlane
50
+#
51
+# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
52
+# screenshots whenever they are needed.
53
+# For more information about the recommended setup visit:
54
+# https://docs.fastlane.tools/best-practices/source-control/#source-control
55
+
56
+fastlane/report.xml
57
+fastlane/Preview.html
58
+fastlane/screenshots
59
+fastlane/test_output
60
+
61
+### Xcode ###
62
+# Xcode
63
+#
64
+# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
65
+
66
+## Build generated
67
+
68
+## Various settings
69
+
70
+## Other
71
+
72
+### Xcode Patch ###
73
+*.xcodeproj/*
74
+!*.xcodeproj/project.pbxproj
75
+!*.xcodeproj/xcshareddata/
76
+!*.xcworkspace/contents.xcworkspacedata
77
+/*.gcno

+ 468
- 0
MongoView.xcodeproj/project.pbxproj View File

@@ -0,0 +1,468 @@
1
+// !$*UTF8*$!
2
+{
3
+	archiveVersion = 1;
4
+	classes = {
5
+	};
6
+	objectVersion = 50;
7
+	objects = {
8
+
9
+/* Begin PBXBuildFile section */
10
+		D60C863923CA2DD100C9DB8E /* ServerConnectWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D60C863723CA2DD100C9DB8E /* ServerConnectWindowController.swift */; };
11
+		D60C863A23CA2DD100C9DB8E /* ServerConnectWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D60C863823CA2DD100C9DB8E /* ServerConnectWindowController.xib */; };
12
+		D60C863F23CA2E2100C9DB8E /* ServerConnectViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D60C863D23CA2E2100C9DB8E /* ServerConnectViewController.swift */; };
13
+		D60C864023CA2E2100C9DB8E /* ServerConnectViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D60C863E23CA2E2100C9DB8E /* ServerConnectViewController.xib */; };
14
+		D63CDEBE23C837DC0012D658 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D63CDEBD23C837DC0012D658 /* AppDelegate.swift */; };
15
+		D63CDEC023C837DD0012D658 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D63CDEBF23C837DD0012D658 /* Assets.xcassets */; };
16
+		D63CDEC323C837DD0012D658 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = D63CDEC123C837DD0012D658 /* MainMenu.xib */; };
17
+		D63CDF1F23C837F10012D658 /* CLibMongoC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D63CDF1623C837F10012D658 /* CLibMongoC.framework */; };
18
+		D63CDF2023C837F10012D658 /* CLibMongoC.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D63CDF1623C837F10012D658 /* CLibMongoC.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
19
+		D63CDF2123C837F10012D658 /* CNIOAtomics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D63CDF1723C837F10012D658 /* CNIOAtomics.framework */; };
20
+		D63CDF2223C837F10012D658 /* CNIOAtomics.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D63CDF1723C837F10012D658 /* CNIOAtomics.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
21
+		D63CDF2323C837F10012D658 /* CNIODarwin.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D63CDF1823C837F10012D658 /* CNIODarwin.framework */; };
22
+		D63CDF2423C837F10012D658 /* CNIODarwin.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D63CDF1823C837F10012D658 /* CNIODarwin.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
23
+		D63CDF2523C837F10012D658 /* CNIOLinux.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D63CDF1923C837F10012D658 /* CNIOLinux.framework */; };
24
+		D63CDF2623C837F10012D658 /* CNIOLinux.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D63CDF1923C837F10012D658 /* CNIOLinux.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
25
+		D63CDF2723C837F10012D658 /* CNIOSHA1.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D63CDF1A23C837F10012D658 /* CNIOSHA1.framework */; };
26
+		D63CDF2823C837F10012D658 /* CNIOSHA1.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D63CDF1A23C837F10012D658 /* CNIOSHA1.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
27
+		D63CDF2923C837F10012D658 /* MongoSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D63CDF1B23C837F10012D658 /* MongoSwift.framework */; };
28
+		D63CDF2A23C837F10012D658 /* MongoSwift.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D63CDF1B23C837F10012D658 /* MongoSwift.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
29
+		D63CDF2B23C837F10012D658 /* MongoSwiftSync.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D63CDF1C23C837F10012D658 /* MongoSwiftSync.framework */; };
30
+		D63CDF2C23C837F10012D658 /* MongoSwiftSync.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D63CDF1C23C837F10012D658 /* MongoSwiftSync.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
31
+		D63CDF2D23C837F10012D658 /* NIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D63CDF1D23C837F10012D658 /* NIO.framework */; };
32
+		D63CDF2E23C837F10012D658 /* NIO.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D63CDF1D23C837F10012D658 /* NIO.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
33
+		D63CDF2F23C837F10012D658 /* NIOConcurrencyHelpers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D63CDF1E23C837F10012D658 /* NIOConcurrencyHelpers.framework */; };
34
+		D63CDF3023C837F10012D658 /* NIOConcurrencyHelpers.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D63CDF1E23C837F10012D658 /* NIOConcurrencyHelpers.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
35
+		D63CDF3723C8381A0012D658 /* Node.swift in Sources */ = {isa = PBXBuildFile; fileRef = D63CDF3323C838190012D658 /* Node.swift */; };
36
+		D63CDF3823C8381A0012D658 /* MongoController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D63CDF3423C838190012D658 /* MongoController.swift */; };
37
+		D63CDF3C23C838470012D658 /* DatabaseWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D63CDF3A23C838470012D658 /* DatabaseWindowController.swift */; };
38
+		D63CDF3D23C838470012D658 /* DatabaseWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D63CDF3B23C838470012D658 /* DatabaseWindowController.xib */; };
39
+		D63CDF4023C839010012D658 /* QueryViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D63CDF3E23C839010012D658 /* QueryViewController.swift */; };
40
+		D63CDF4123C839010012D658 /* QueryViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D63CDF3F23C839010012D658 /* QueryViewController.xib */; };
41
+		D63CDF4423C970C50012D658 /* DatabaseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D63CDF4223C970C50012D658 /* DatabaseViewController.swift */; };
42
+		D63CDF4523C970C50012D658 /* DatabaseViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D63CDF4323C970C50012D658 /* DatabaseViewController.xib */; };
43
+/* End PBXBuildFile section */
44
+
45
+/* Begin PBXCopyFilesBuildPhase section */
46
+		D63CDF3123C837F10012D658 /* Embed Frameworks */ = {
47
+			isa = PBXCopyFilesBuildPhase;
48
+			buildActionMask = 2147483647;
49
+			dstPath = "";
50
+			dstSubfolderSpec = 10;
51
+			files = (
52
+				D63CDF2823C837F10012D658 /* CNIOSHA1.framework in Embed Frameworks */,
53
+				D63CDF2623C837F10012D658 /* CNIOLinux.framework in Embed Frameworks */,
54
+				D63CDF2423C837F10012D658 /* CNIODarwin.framework in Embed Frameworks */,
55
+				D63CDF2A23C837F10012D658 /* MongoSwift.framework in Embed Frameworks */,
56
+				D63CDF2223C837F10012D658 /* CNIOAtomics.framework in Embed Frameworks */,
57
+				D63CDF2023C837F10012D658 /* CLibMongoC.framework in Embed Frameworks */,
58
+				D63CDF2C23C837F10012D658 /* MongoSwiftSync.framework in Embed Frameworks */,
59
+				D63CDF3023C837F10012D658 /* NIOConcurrencyHelpers.framework in Embed Frameworks */,
60
+				D63CDF2E23C837F10012D658 /* NIO.framework in Embed Frameworks */,
61
+			);
62
+			name = "Embed Frameworks";
63
+			runOnlyForDeploymentPostprocessing = 0;
64
+		};
65
+/* End PBXCopyFilesBuildPhase section */
66
+
67
+/* Begin PBXFileReference section */
68
+		D60C863723CA2DD100C9DB8E /* ServerConnectWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConnectWindowController.swift; sourceTree = "<group>"; };
69
+		D60C863823CA2DD100C9DB8E /* ServerConnectWindowController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ServerConnectWindowController.xib; sourceTree = "<group>"; };
70
+		D60C863D23CA2E2100C9DB8E /* ServerConnectViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConnectViewController.swift; sourceTree = "<group>"; };
71
+		D60C863E23CA2E2100C9DB8E /* ServerConnectViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ServerConnectViewController.xib; sourceTree = "<group>"; };
72
+		D63CDEBA23C837DC0012D658 /* MongoView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MongoView.app; sourceTree = BUILT_PRODUCTS_DIR; };
73
+		D63CDEBD23C837DC0012D658 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
74
+		D63CDEBF23C837DD0012D658 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
75
+		D63CDEC223C837DD0012D658 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
76
+		D63CDEC423C837DD0012D658 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
77
+		D63CDEC523C837DD0012D658 /* MongoView.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = MongoView.entitlements; sourceTree = "<group>"; };
78
+		D63CDF1623C837F10012D658 /* CLibMongoC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = CLibMongoC.framework; sourceTree = BUILT_PRODUCTS_DIR; };
79
+		D63CDF1723C837F10012D658 /* CNIOAtomics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = CNIOAtomics.framework; sourceTree = BUILT_PRODUCTS_DIR; };
80
+		D63CDF1823C837F10012D658 /* CNIODarwin.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = CNIODarwin.framework; sourceTree = BUILT_PRODUCTS_DIR; };
81
+		D63CDF1923C837F10012D658 /* CNIOLinux.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = CNIOLinux.framework; sourceTree = BUILT_PRODUCTS_DIR; };
82
+		D63CDF1A23C837F10012D658 /* CNIOSHA1.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = CNIOSHA1.framework; sourceTree = BUILT_PRODUCTS_DIR; };
83
+		D63CDF1B23C837F10012D658 /* MongoSwift.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = MongoSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; };
84
+		D63CDF1C23C837F10012D658 /* MongoSwiftSync.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = MongoSwiftSync.framework; sourceTree = BUILT_PRODUCTS_DIR; };
85
+		D63CDF1D23C837F10012D658 /* NIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = NIO.framework; sourceTree = BUILT_PRODUCTS_DIR; };
86
+		D63CDF1E23C837F10012D658 /* NIOConcurrencyHelpers.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = NIOConcurrencyHelpers.framework; sourceTree = BUILT_PRODUCTS_DIR; };
87
+		D63CDF3323C838190012D658 /* Node.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Node.swift; sourceTree = "<group>"; };
88
+		D63CDF3423C838190012D658 /* MongoController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MongoController.swift; sourceTree = "<group>"; };
89
+		D63CDF3A23C838470012D658 /* DatabaseWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatabaseWindowController.swift; sourceTree = "<group>"; };
90
+		D63CDF3B23C838470012D658 /* DatabaseWindowController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = DatabaseWindowController.xib; sourceTree = "<group>"; };
91
+		D63CDF3E23C839010012D658 /* QueryViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueryViewController.swift; sourceTree = "<group>"; };
92
+		D63CDF3F23C839010012D658 /* QueryViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = QueryViewController.xib; sourceTree = "<group>"; };
93
+		D63CDF4223C970C50012D658 /* DatabaseViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatabaseViewController.swift; sourceTree = "<group>"; };
94
+		D63CDF4323C970C50012D658 /* DatabaseViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = DatabaseViewController.xib; sourceTree = "<group>"; };
95
+/* End PBXFileReference section */
96
+
97
+/* Begin PBXFrameworksBuildPhase section */
98
+		D63CDEB723C837DC0012D658 /* Frameworks */ = {
99
+			isa = PBXFrameworksBuildPhase;
100
+			buildActionMask = 2147483647;
101
+			files = (
102
+				D63CDF2723C837F10012D658 /* CNIOSHA1.framework in Frameworks */,
103
+				D63CDF2523C837F10012D658 /* CNIOLinux.framework in Frameworks */,
104
+				D63CDF2323C837F10012D658 /* CNIODarwin.framework in Frameworks */,
105
+				D63CDF2923C837F10012D658 /* MongoSwift.framework in Frameworks */,
106
+				D63CDF2123C837F10012D658 /* CNIOAtomics.framework in Frameworks */,
107
+				D63CDF1F23C837F10012D658 /* CLibMongoC.framework in Frameworks */,
108
+				D63CDF2B23C837F10012D658 /* MongoSwiftSync.framework in Frameworks */,
109
+				D63CDF2F23C837F10012D658 /* NIOConcurrencyHelpers.framework in Frameworks */,
110
+				D63CDF2D23C837F10012D658 /* NIO.framework in Frameworks */,
111
+			);
112
+			runOnlyForDeploymentPostprocessing = 0;
113
+		};
114
+/* End PBXFrameworksBuildPhase section */
115
+
116
+/* Begin PBXGroup section */
117
+		D60C863B23CA2DD600C9DB8E /* Windows */ = {
118
+			isa = PBXGroup;
119
+			children = (
120
+				D60C863723CA2DD100C9DB8E /* ServerConnectWindowController.swift */,
121
+				D60C863823CA2DD100C9DB8E /* ServerConnectWindowController.xib */,
122
+				D63CDF3A23C838470012D658 /* DatabaseWindowController.swift */,
123
+				D63CDF3B23C838470012D658 /* DatabaseWindowController.xib */,
124
+			);
125
+			path = Windows;
126
+			sourceTree = "<group>";
127
+		};
128
+		D60C863C23CA2DDD00C9DB8E /* View Controllers */ = {
129
+			isa = PBXGroup;
130
+			children = (
131
+				D60C863D23CA2E2100C9DB8E /* ServerConnectViewController.swift */,
132
+				D60C863E23CA2E2100C9DB8E /* ServerConnectViewController.xib */,
133
+				D63CDF4223C970C50012D658 /* DatabaseViewController.swift */,
134
+				D63CDF4323C970C50012D658 /* DatabaseViewController.xib */,
135
+				D63CDF3E23C839010012D658 /* QueryViewController.swift */,
136
+				D63CDF3F23C839010012D658 /* QueryViewController.xib */,
137
+			);
138
+			path = "View Controllers";
139
+			sourceTree = "<group>";
140
+		};
141
+		D63CDEB123C837DC0012D658 = {
142
+			isa = PBXGroup;
143
+			children = (
144
+				D63CDEBC23C837DC0012D658 /* MongoView */,
145
+				D63CDEBB23C837DC0012D658 /* Products */,
146
+				D63CDF1523C837F10012D658 /* Frameworks */,
147
+			);
148
+			sourceTree = "<group>";
149
+		};
150
+		D63CDEBB23C837DC0012D658 /* Products */ = {
151
+			isa = PBXGroup;
152
+			children = (
153
+				D63CDEBA23C837DC0012D658 /* MongoView.app */,
154
+			);
155
+			name = Products;
156
+			sourceTree = "<group>";
157
+		};
158
+		D63CDEBC23C837DC0012D658 /* MongoView */ = {
159
+			isa = PBXGroup;
160
+			children = (
161
+				D63CDEBD23C837DC0012D658 /* AppDelegate.swift */,
162
+				D63CDF3423C838190012D658 /* MongoController.swift */,
163
+				D63CDF3323C838190012D658 /* Node.swift */,
164
+				D60C863B23CA2DD600C9DB8E /* Windows */,
165
+				D60C863C23CA2DDD00C9DB8E /* View Controllers */,
166
+				D63CDEBF23C837DD0012D658 /* Assets.xcassets */,
167
+				D63CDEC123C837DD0012D658 /* MainMenu.xib */,
168
+				D63CDEC423C837DD0012D658 /* Info.plist */,
169
+				D63CDEC523C837DD0012D658 /* MongoView.entitlements */,
170
+			);
171
+			path = MongoView;
172
+			sourceTree = "<group>";
173
+		};
174
+		D63CDF1523C837F10012D658 /* Frameworks */ = {
175
+			isa = PBXGroup;
176
+			children = (
177
+				D63CDF1623C837F10012D658 /* CLibMongoC.framework */,
178
+				D63CDF1723C837F10012D658 /* CNIOAtomics.framework */,
179
+				D63CDF1823C837F10012D658 /* CNIODarwin.framework */,
180
+				D63CDF1923C837F10012D658 /* CNIOLinux.framework */,
181
+				D63CDF1A23C837F10012D658 /* CNIOSHA1.framework */,
182
+				D63CDF1B23C837F10012D658 /* MongoSwift.framework */,
183
+				D63CDF1C23C837F10012D658 /* MongoSwiftSync.framework */,
184
+				D63CDF1D23C837F10012D658 /* NIO.framework */,
185
+				D63CDF1E23C837F10012D658 /* NIOConcurrencyHelpers.framework */,
186
+			);
187
+			name = Frameworks;
188
+			sourceTree = "<group>";
189
+		};
190
+/* End PBXGroup section */
191
+
192
+/* Begin PBXNativeTarget section */
193
+		D63CDEB923C837DC0012D658 /* MongoView */ = {
194
+			isa = PBXNativeTarget;
195
+			buildConfigurationList = D63CDEC823C837DD0012D658 /* Build configuration list for PBXNativeTarget "MongoView" */;
196
+			buildPhases = (
197
+				D63CDEB623C837DC0012D658 /* Sources */,
198
+				D63CDEB723C837DC0012D658 /* Frameworks */,
199
+				D63CDEB823C837DC0012D658 /* Resources */,
200
+				D63CDF3123C837F10012D658 /* Embed Frameworks */,
201
+			);
202
+			buildRules = (
203
+			);
204
+			dependencies = (
205
+			);
206
+			name = MongoView;
207
+			productName = MongoView;
208
+			productReference = D63CDEBA23C837DC0012D658 /* MongoView.app */;
209
+			productType = "com.apple.product-type.application";
210
+		};
211
+/* End PBXNativeTarget section */
212
+
213
+/* Begin PBXProject section */
214
+		D63CDEB223C837DC0012D658 /* Project object */ = {
215
+			isa = PBXProject;
216
+			attributes = {
217
+				LastSwiftUpdateCheck = 1130;
218
+				LastUpgradeCheck = 1130;
219
+				ORGANIZATIONNAME = Shadowfacts;
220
+				TargetAttributes = {
221
+					D63CDEB923C837DC0012D658 = {
222
+						CreatedOnToolsVersion = 11.3;
223
+					};
224
+				};
225
+			};
226
+			buildConfigurationList = D63CDEB523C837DC0012D658 /* Build configuration list for PBXProject "MongoView" */;
227
+			compatibilityVersion = "Xcode 9.3";
228
+			developmentRegion = en;
229
+			hasScannedForEncodings = 0;
230
+			knownRegions = (
231
+				en,
232
+				Base,
233
+			);
234
+			mainGroup = D63CDEB123C837DC0012D658;
235
+			productRefGroup = D63CDEBB23C837DC0012D658 /* Products */;
236
+			projectDirPath = "";
237
+			projectRoot = "";
238
+			targets = (
239
+				D63CDEB923C837DC0012D658 /* MongoView */,
240
+			);
241
+		};
242
+/* End PBXProject section */
243
+
244
+/* Begin PBXResourcesBuildPhase section */
245
+		D63CDEB823C837DC0012D658 /* Resources */ = {
246
+			isa = PBXResourcesBuildPhase;
247
+			buildActionMask = 2147483647;
248
+			files = (
249
+				D60C864023CA2E2100C9DB8E /* ServerConnectViewController.xib in Resources */,
250
+				D63CDEC023C837DD0012D658 /* Assets.xcassets in Resources */,
251
+				D60C863A23CA2DD100C9DB8E /* ServerConnectWindowController.xib in Resources */,
252
+				D63CDF4523C970C50012D658 /* DatabaseViewController.xib in Resources */,
253
+				D63CDF3D23C838470012D658 /* DatabaseWindowController.xib in Resources */,
254
+				D63CDEC323C837DD0012D658 /* MainMenu.xib in Resources */,
255
+				D63CDF4123C839010012D658 /* QueryViewController.xib in Resources */,
256
+			);
257
+			runOnlyForDeploymentPostprocessing = 0;
258
+		};
259
+/* End PBXResourcesBuildPhase section */
260
+
261
+/* Begin PBXSourcesBuildPhase section */
262
+		D63CDEB623C837DC0012D658 /* Sources */ = {
263
+			isa = PBXSourcesBuildPhase;
264
+			buildActionMask = 2147483647;
265
+			files = (
266
+				D63CDEBE23C837DC0012D658 /* AppDelegate.swift in Sources */,
267
+				D63CDF3823C8381A0012D658 /* MongoController.swift in Sources */,
268
+				D60C863923CA2DD100C9DB8E /* ServerConnectWindowController.swift in Sources */,
269
+				D63CDF3723C8381A0012D658 /* Node.swift in Sources */,
270
+				D60C863F23CA2E2100C9DB8E /* ServerConnectViewController.swift in Sources */,
271
+				D63CDF4423C970C50012D658 /* DatabaseViewController.swift in Sources */,
272
+				D63CDF3C23C838470012D658 /* DatabaseWindowController.swift in Sources */,
273
+				D63CDF4023C839010012D658 /* QueryViewController.swift in Sources */,
274
+			);
275
+			runOnlyForDeploymentPostprocessing = 0;
276
+		};
277
+/* End PBXSourcesBuildPhase section */
278
+
279
+/* Begin PBXVariantGroup section */
280
+		D63CDEC123C837DD0012D658 /* MainMenu.xib */ = {
281
+			isa = PBXVariantGroup;
282
+			children = (
283
+				D63CDEC223C837DD0012D658 /* Base */,
284
+			);
285
+			name = MainMenu.xib;
286
+			sourceTree = "<group>";
287
+		};
288
+/* End PBXVariantGroup section */
289
+
290
+/* Begin XCBuildConfiguration section */
291
+		D63CDEC623C837DD0012D658 /* Debug */ = {
292
+			isa = XCBuildConfiguration;
293
+			buildSettings = {
294
+				ALWAYS_SEARCH_USER_PATHS = NO;
295
+				CLANG_ANALYZER_NONNULL = YES;
296
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
297
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
298
+				CLANG_CXX_LIBRARY = "libc++";
299
+				CLANG_ENABLE_MODULES = YES;
300
+				CLANG_ENABLE_OBJC_ARC = YES;
301
+				CLANG_ENABLE_OBJC_WEAK = YES;
302
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
303
+				CLANG_WARN_BOOL_CONVERSION = YES;
304
+				CLANG_WARN_COMMA = YES;
305
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
306
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
307
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
308
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
309
+				CLANG_WARN_EMPTY_BODY = YES;
310
+				CLANG_WARN_ENUM_CONVERSION = YES;
311
+				CLANG_WARN_INFINITE_RECURSION = YES;
312
+				CLANG_WARN_INT_CONVERSION = YES;
313
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
314
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
315
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
316
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
317
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
318
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
319
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
320
+				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
321
+				CLANG_WARN_UNREACHABLE_CODE = YES;
322
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
323
+				COPY_PHASE_STRIP = NO;
324
+				DEBUG_INFORMATION_FORMAT = dwarf;
325
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
326
+				ENABLE_TESTABILITY = YES;
327
+				GCC_C_LANGUAGE_STANDARD = gnu11;
328
+				GCC_DYNAMIC_NO_PIC = NO;
329
+				GCC_NO_COMMON_BLOCKS = YES;
330
+				GCC_OPTIMIZATION_LEVEL = 0;
331
+				GCC_PREPROCESSOR_DEFINITIONS = (
332
+					"DEBUG=1",
333
+					"$(inherited)",
334
+				);
335
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
336
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
337
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
338
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
339
+				GCC_WARN_UNUSED_FUNCTION = YES;
340
+				GCC_WARN_UNUSED_VARIABLE = YES;
341
+				MACOSX_DEPLOYMENT_TARGET = 10.15;
342
+				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
343
+				MTL_FAST_MATH = YES;
344
+				ONLY_ACTIVE_ARCH = YES;
345
+				SDKROOT = macosx;
346
+				SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
347
+				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
348
+			};
349
+			name = Debug;
350
+		};
351
+		D63CDEC723C837DD0012D658 /* Release */ = {
352
+			isa = XCBuildConfiguration;
353
+			buildSettings = {
354
+				ALWAYS_SEARCH_USER_PATHS = NO;
355
+				CLANG_ANALYZER_NONNULL = YES;
356
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
357
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
358
+				CLANG_CXX_LIBRARY = "libc++";
359
+				CLANG_ENABLE_MODULES = YES;
360
+				CLANG_ENABLE_OBJC_ARC = YES;
361
+				CLANG_ENABLE_OBJC_WEAK = YES;
362
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
363
+				CLANG_WARN_BOOL_CONVERSION = YES;
364
+				CLANG_WARN_COMMA = YES;
365
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
366
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
367
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
368
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
369
+				CLANG_WARN_EMPTY_BODY = YES;
370
+				CLANG_WARN_ENUM_CONVERSION = YES;
371
+				CLANG_WARN_INFINITE_RECURSION = YES;
372
+				CLANG_WARN_INT_CONVERSION = YES;
373
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
374
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
375
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
376
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
377
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
378
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
379
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
380
+				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
381
+				CLANG_WARN_UNREACHABLE_CODE = YES;
382
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
383
+				COPY_PHASE_STRIP = NO;
384
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
385
+				ENABLE_NS_ASSERTIONS = NO;
386
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
387
+				GCC_C_LANGUAGE_STANDARD = gnu11;
388
+				GCC_NO_COMMON_BLOCKS = YES;
389
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
390
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
391
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
392
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
393
+				GCC_WARN_UNUSED_FUNCTION = YES;
394
+				GCC_WARN_UNUSED_VARIABLE = YES;
395
+				MACOSX_DEPLOYMENT_TARGET = 10.15;
396
+				MTL_ENABLE_DEBUG_INFO = NO;
397
+				MTL_FAST_MATH = YES;
398
+				SDKROOT = macosx;
399
+				SWIFT_COMPILATION_MODE = wholemodule;
400
+				SWIFT_OPTIMIZATION_LEVEL = "-O";
401
+			};
402
+			name = Release;
403
+		};
404
+		D63CDEC923C837DD0012D658 /* Debug */ = {
405
+			isa = XCBuildConfiguration;
406
+			buildSettings = {
407
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
408
+				CODE_SIGN_ENTITLEMENTS = MongoView/MongoView.entitlements;
409
+				CODE_SIGN_STYLE = Automatic;
410
+				COMBINE_HIDPI_IMAGES = YES;
411
+				DEVELOPMENT_TEAM = HGYVAQA9FW;
412
+				ENABLE_HARDENED_RUNTIME = YES;
413
+				INFOPLIST_FILE = MongoView/Info.plist;
414
+				LD_RUNPATH_SEARCH_PATHS = (
415
+					"$(inherited)",
416
+					"@executable_path/../Frameworks",
417
+				);
418
+				PRODUCT_BUNDLE_IDENTIFIER = net.shadowfacts.MongoView;
419
+				PRODUCT_NAME = "$(TARGET_NAME)";
420
+				SWIFT_VERSION = 5.0;
421
+			};
422
+			name = Debug;
423
+		};
424
+		D63CDECA23C837DD0012D658 /* Release */ = {
425
+			isa = XCBuildConfiguration;
426
+			buildSettings = {
427
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
428
+				CODE_SIGN_ENTITLEMENTS = MongoView/MongoView.entitlements;
429
+				CODE_SIGN_STYLE = Automatic;
430
+				COMBINE_HIDPI_IMAGES = YES;
431
+				DEVELOPMENT_TEAM = HGYVAQA9FW;
432
+				ENABLE_HARDENED_RUNTIME = YES;
433
+				INFOPLIST_FILE = MongoView/Info.plist;
434
+				LD_RUNPATH_SEARCH_PATHS = (
435
+					"$(inherited)",
436
+					"@executable_path/../Frameworks",
437
+				);
438
+				PRODUCT_BUNDLE_IDENTIFIER = net.shadowfacts.MongoView;
439
+				PRODUCT_NAME = "$(TARGET_NAME)";
440
+				SWIFT_VERSION = 5.0;
441
+			};
442
+			name = Release;
443
+		};
444
+/* End XCBuildConfiguration section */
445
+
446
+/* Begin XCConfigurationList section */
447
+		D63CDEB523C837DC0012D658 /* Build configuration list for PBXProject "MongoView" */ = {
448
+			isa = XCConfigurationList;
449
+			buildConfigurations = (
450
+				D63CDEC623C837DD0012D658 /* Debug */,
451
+				D63CDEC723C837DD0012D658 /* Release */,
452
+			);
453
+			defaultConfigurationIsVisible = 0;
454
+			defaultConfigurationName = Release;
455
+		};
456
+		D63CDEC823C837DD0012D658 /* Build configuration list for PBXNativeTarget "MongoView" */ = {
457
+			isa = XCConfigurationList;
458
+			buildConfigurations = (
459
+				D63CDEC923C837DD0012D658 /* Debug */,
460
+				D63CDECA23C837DD0012D658 /* Release */,
461
+			);
462
+			defaultConfigurationIsVisible = 0;
463
+			defaultConfigurationName = Release;
464
+		};
465
+/* End XCConfigurationList section */
466
+	};
467
+	rootObject = D63CDEB223C837DC0012D658 /* Project object */;
468
+}

+ 10
- 0
MongoView.xcworkspace/contents.xcworkspacedata View File

@@ -0,0 +1,10 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<Workspace
3
+   version = "1.0">
4
+   <FileRef
5
+      location = "container:MongoView.xcodeproj">
6
+   </FileRef>
7
+   <FileRef
8
+      location = "group:../mongo-swift-driver/MongoSwift.xcodeproj">
9
+   </FileRef>
10
+</Workspace>

+ 8
- 0
MongoView.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist View File

@@ -0,0 +1,8 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+<plist version="1.0">
4
+<dict>
5
+	<key>IDEDidComputeMac32BitWarning</key>
6
+	<true/>
7
+</dict>
8
+</plist>

+ 74
- 0
MongoView/AppDelegate.swift View File

@@ -0,0 +1,74 @@
1
+//
2
+//  AppDelegate.swift
3
+//  MongoView
4
+//
5
+//  Created by Shadowfacts on 1/9/20.
6
+//  Copyright © 2020 Shadowfacts. All rights reserved.
7
+//
8
+
9
+import Cocoa
10
+
11
+@NSApplicationMain
12
+class AppDelegate: NSObject, NSApplicationDelegate {
13
+
14
+    var windowControllers = [DatabaseWindowController]()
15
+    
16
+    var serverConnectWindowController: ServerConnectWindowController?
17
+
18
+    func applicationDidFinishLaunching(_ aNotification: Notification) {
19
+        let wc = DatabaseWindowController()
20
+        windowControllers.append(wc)
21
+        wc.showWindow(nil)
22
+    }
23
+
24
+    func applicationWillTerminate(_ aNotification: Notification) {
25
+    }
26
+    
27
+    func newWindow(mongoController: MongoController?, collection: DatabaseCollection? = nil, addToTabGroup: Bool = true) {
28
+        let wc = DatabaseWindowController()
29
+        wc.mongoController = mongoController
30
+        wc.initialCollection = collection
31
+        windowControllers.append(wc)
32
+        
33
+        if addToTabGroup,
34
+            let tabGroup = windowControllers.first(where: { $0.window!.isKeyWindow })?.window?.tabGroup {
35
+            tabGroup.addWindow(wc.window!)
36
+            tabGroup.selectedWindow = wc.window!
37
+        } else {
38
+            wc.showWindow(nil)
39
+        }
40
+    }
41
+
42
+    @IBAction func newTab(_ sender: Any) {
43
+        let mongoController = windowControllers.first { $0.window!.isKeyWindow }?.mongoController
44
+        newWindow(mongoController: mongoController)
45
+    }
46
+    
47
+    @IBAction func connectToServer(_ sender: Any) {
48
+        guard serverConnectWindowController == nil else { return }
49
+        
50
+        let wc = ServerConnectWindowController()
51
+        wc.delegate = self
52
+        serverConnectWindowController = wc
53
+        wc.showWindow(nil)
54
+    }
55
+
56
+}
57
+
58
+extension AppDelegate: NSMenuItemValidation {
59
+    func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
60
+        if menuItem.action == #selector(connectToServer(_:)) {
61
+            return serverConnectWindowController == nil
62
+        }
63
+        return true
64
+    }
65
+}
66
+
67
+extension AppDelegate: ServerConnectViewControllerDelegate {
68
+    func connectToServer(mongoController: MongoController) {
69
+        serverConnectWindowController!.close()
70
+        serverConnectWindowController = nil
71
+        
72
+        newWindow(mongoController: mongoController, addToTabGroup: false)
73
+    }
74
+}

+ 58
- 0
MongoView/Assets.xcassets/AppIcon.appiconset/Contents.json View File

@@ -0,0 +1,58 @@
1
+{
2
+  "images" : [
3
+    {
4
+      "idiom" : "mac",
5
+      "size" : "16x16",
6
+      "scale" : "1x"
7
+    },
8
+    {
9
+      "idiom" : "mac",
10
+      "size" : "16x16",
11
+      "scale" : "2x"
12
+    },
13
+    {
14
+      "idiom" : "mac",
15
+      "size" : "32x32",
16
+      "scale" : "1x"
17
+    },
18
+    {
19
+      "idiom" : "mac",
20
+      "size" : "32x32",
21
+      "scale" : "2x"
22
+    },
23
+    {
24
+      "idiom" : "mac",
25
+      "size" : "128x128",
26
+      "scale" : "1x"
27
+    },
28
+    {
29
+      "idiom" : "mac",
30
+      "size" : "128x128",
31
+      "scale" : "2x"
32
+    },
33
+    {
34
+      "idiom" : "mac",
35
+      "size" : "256x256",
36
+      "scale" : "1x"
37
+    },
38
+    {
39
+      "idiom" : "mac",
40
+      "size" : "256x256",
41
+      "scale" : "2x"
42
+    },
43
+    {
44
+      "idiom" : "mac",
45
+      "size" : "512x512",
46
+      "scale" : "1x"
47
+    },
48
+    {
49
+      "idiom" : "mac",
50
+      "size" : "512x512",
51
+      "scale" : "2x"
52
+    }
53
+  ],
54
+  "info" : {
55
+    "version" : 1,
56
+    "author" : "xcode"
57
+  }
58
+}

+ 6
- 0
MongoView/Assets.xcassets/Contents.json View File

@@ -0,0 +1,6 @@
1
+{
2
+  "info" : {
3
+    "version" : 1,
4
+    "author" : "xcode"
5
+  }
6
+}

+ 449
- 0
MongoView/Base.lproj/MainMenu.xib View File

@@ -0,0 +1,449 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="15702" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
3
+    <dependencies>
4
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15702"/>
5
+    </dependencies>
6
+    <objects>
7
+        <customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
8
+            <connections>
9
+                <outlet property="delegate" destination="Voe-Tx-rLC" id="GzC-gU-4Uq"/>
10
+            </connections>
11
+        </customObject>
12
+        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
13
+        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
14
+        <customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModule="MongoView" customModuleProvider="target"/>
15
+        <customObject id="YLy-65-1bz" customClass="NSFontManager"/>
16
+        <menu title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
17
+            <items>
18
+                <menuItem title="MongoView" id="1Xt-HY-uBw">
19
+                    <modifierMask key="keyEquivalentModifierMask"/>
20
+                    <menu key="submenu" title="MongoView" systemMenu="apple" id="uQy-DD-JDr">
21
+                        <items>
22
+                            <menuItem title="About MongoView" id="5kV-Vb-QxS">
23
+                                <modifierMask key="keyEquivalentModifierMask"/>
24
+                                <connections>
25
+                                    <action selector="orderFrontStandardAboutPanel:" target="-1" id="Exp-CZ-Vem"/>
26
+                                </connections>
27
+                            </menuItem>
28
+                            <menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/>
29
+                            <menuItem title="Preferences…" keyEquivalent="," id="BOF-NM-1cW"/>
30
+                            <menuItem isSeparatorItem="YES" id="wFC-TO-SCJ"/>
31
+                            <menuItem title="Services" id="NMo-om-nkz">
32
+                                <modifierMask key="keyEquivalentModifierMask"/>
33
+                                <menu key="submenu" title="Services" systemMenu="services" id="hz9-B4-Xy5"/>
34
+                            </menuItem>
35
+                            <menuItem isSeparatorItem="YES" id="4je-JR-u6R"/>
36
+                            <menuItem title="Hide MongoView" keyEquivalent="h" id="Olw-nP-bQN">
37
+                                <connections>
38
+                                    <action selector="hide:" target="-1" id="PnN-Uc-m68"/>
39
+                                </connections>
40
+                            </menuItem>
41
+                            <menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO">
42
+                                <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
43
+                                <connections>
44
+                                    <action selector="hideOtherApplications:" target="-1" id="VT4-aY-XCT"/>
45
+                                </connections>
46
+                            </menuItem>
47
+                            <menuItem title="Show All" id="Kd2-mp-pUS">
48
+                                <modifierMask key="keyEquivalentModifierMask"/>
49
+                                <connections>
50
+                                    <action selector="unhideAllApplications:" target="-1" id="Dhg-Le-xox"/>
51
+                                </connections>
52
+                            </menuItem>
53
+                            <menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/>
54
+                            <menuItem title="Quit MongoView" keyEquivalent="q" id="4sb-4s-VLi">
55
+                                <connections>
56
+                                    <action selector="terminate:" target="-1" id="Te7-pn-YzF"/>
57
+                                </connections>
58
+                            </menuItem>
59
+                        </items>
60
+                    </menu>
61
+                </menuItem>
62
+                <menuItem title="File" id="dMs-cI-mzQ">
63
+                    <modifierMask key="keyEquivalentModifierMask"/>
64
+                    <menu key="submenu" title="File" id="bib-Uj-vzu">
65
+                        <items>
66
+                            <menuItem title="New" keyEquivalent="n" id="Was-JA-tGl">
67
+                                <connections>
68
+                                    <action selector="newDocument:" target="-1" id="4Si-XN-c54"/>
69
+                                </connections>
70
+                            </menuItem>
71
+                            <menuItem title="New Tab" keyEquivalent="t" id="9AK-Fk-TxU">
72
+                                <connections>
73
+                                    <action selector="newTab:" target="Voe-Tx-rLC" id="JyK-8N-xQT"/>
74
+                                </connections>
75
+                            </menuItem>
76
+                            <menuItem title="Open…" keyEquivalent="o" id="IAo-SY-fd9">
77
+                                <connections>
78
+                                    <action selector="openDocument:" target="-1" id="bVn-NM-KNZ"/>
79
+                                </connections>
80
+                            </menuItem>
81
+                            <menuItem title="Open Recent" id="tXI-mr-wws">
82
+                                <modifierMask key="keyEquivalentModifierMask"/>
83
+                                <menu key="submenu" title="Open Recent" systemMenu="recentDocuments" id="oas-Oc-fiZ">
84
+                                    <items>
85
+                                        <menuItem title="Clear Menu" id="vNY-rz-j42">
86
+                                            <modifierMask key="keyEquivalentModifierMask"/>
87
+                                            <connections>
88
+                                                <action selector="clearRecentDocuments:" target="-1" id="Daa-9d-B3U"/>
89
+                                            </connections>
90
+                                        </menuItem>
91
+                                    </items>
92
+                                </menu>
93
+                            </menuItem>
94
+                            <menuItem isSeparatorItem="YES" id="m54-Is-iLE"/>
95
+                            <menuItem title="Close" keyEquivalent="w" id="DVo-aG-piG">
96
+                                <connections>
97
+                                    <action selector="performClose:" target="-1" id="HmO-Ls-i7Q"/>
98
+                                </connections>
99
+                            </menuItem>
100
+                            <menuItem title="Save…" keyEquivalent="s" id="pxx-59-PXV">
101
+                                <connections>
102
+                                    <action selector="saveDocument:" target="-1" id="teZ-XB-qJY"/>
103
+                                </connections>
104
+                            </menuItem>
105
+                            <menuItem title="Save As…" keyEquivalent="S" id="Bw7-FT-i3A">
106
+                                <connections>
107
+                                    <action selector="saveDocumentAs:" target="-1" id="mDf-zr-I0C"/>
108
+                                </connections>
109
+                            </menuItem>
110
+                            <menuItem title="Revert to Saved" keyEquivalent="r" id="KaW-ft-85H">
111
+                                <connections>
112
+                                    <action selector="revertDocumentToSaved:" target="-1" id="iJ3-Pv-kwq"/>
113
+                                </connections>
114
+                            </menuItem>
115
+                            <menuItem isSeparatorItem="YES" id="aJh-i4-bef"/>
116
+                            <menuItem title="Page Setup…" keyEquivalent="P" id="qIS-W8-SiK">
117
+                                <modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
118
+                                <connections>
119
+                                    <action selector="runPageLayout:" target="-1" id="Din-rz-gC5"/>
120
+                                </connections>
121
+                            </menuItem>
122
+                            <menuItem title="Print…" keyEquivalent="p" id="aTl-1u-JFS">
123
+                                <connections>
124
+                                    <action selector="print:" target="-1" id="qaZ-4w-aoO"/>
125
+                                </connections>
126
+                            </menuItem>
127
+                        </items>
128
+                    </menu>
129
+                </menuItem>
130
+                <menuItem title="Edit" id="5QF-Oa-p0T">
131
+                    <modifierMask key="keyEquivalentModifierMask"/>
132
+                    <menu key="submenu" title="Edit" id="W48-6f-4Dl">
133
+                        <items>
134
+                            <menuItem title="Undo" keyEquivalent="z" id="dRJ-4n-Yzg">
135
+                                <connections>
136
+                                    <action selector="undo:" target="-1" id="M6e-cu-g7V"/>
137
+                                </connections>
138
+                            </menuItem>
139
+                            <menuItem title="Redo" keyEquivalent="Z" id="6dh-zS-Vam">
140
+                                <connections>
141
+                                    <action selector="redo:" target="-1" id="oIA-Rs-6OD"/>
142
+                                </connections>
143
+                            </menuItem>
144
+                            <menuItem isSeparatorItem="YES" id="WRV-NI-Exz"/>
145
+                            <menuItem title="Cut" keyEquivalent="x" id="uRl-iY-unG">
146
+                                <connections>
147
+                                    <action selector="cut:" target="-1" id="YJe-68-I9s"/>
148
+                                </connections>
149
+                            </menuItem>
150
+                            <menuItem title="Copy" keyEquivalent="c" id="x3v-GG-iWU">
151
+                                <connections>
152
+                                    <action selector="copy:" target="-1" id="G1f-GL-Joy"/>
153
+                                </connections>
154
+                            </menuItem>
155
+                            <menuItem title="Paste" keyEquivalent="v" id="gVA-U4-sdL">
156
+                                <connections>
157
+                                    <action selector="paste:" target="-1" id="UvS-8e-Qdg"/>
158
+                                </connections>
159
+                            </menuItem>
160
+                            <menuItem title="Paste and Match Style" keyEquivalent="V" id="WeT-3V-zwk">
161
+                                <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
162
+                                <connections>
163
+                                    <action selector="pasteAsPlainText:" target="-1" id="cEh-KX-wJQ"/>
164
+                                </connections>
165
+                            </menuItem>
166
+                            <menuItem title="Delete" id="pa3-QI-u2k">
167
+                                <modifierMask key="keyEquivalentModifierMask"/>
168
+                                <connections>
169
+                                    <action selector="delete:" target="-1" id="0Mk-Ml-PaM"/>
170
+                                </connections>
171
+                            </menuItem>
172
+                            <menuItem title="Select All" keyEquivalent="a" id="Ruw-6m-B2m">
173
+                                <connections>
174
+                                    <action selector="selectAll:" target="-1" id="VNm-Mi-diN"/>
175
+                                </connections>
176
+                            </menuItem>
177
+                            <menuItem isSeparatorItem="YES" id="uyl-h8-XO2"/>
178
+                            <menuItem title="Find" id="4EN-yA-p0u">
179
+                                <modifierMask key="keyEquivalentModifierMask"/>
180
+                                <menu key="submenu" title="Find" id="1b7-l0-nxx">
181
+                                    <items>
182
+                                        <menuItem title="Find…" tag="1" keyEquivalent="f" id="Xz5-n4-O0W">
183
+                                            <connections>
184
+                                                <action selector="performFindPanelAction:" target="-1" id="cD7-Qs-BN4"/>
185
+                                            </connections>
186
+                                        </menuItem>
187
+                                        <menuItem title="Find and Replace…" tag="12" keyEquivalent="f" id="YEy-JH-Tfz">
188
+                                            <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
189
+                                            <connections>
190
+                                                <action selector="performFindPanelAction:" target="-1" id="WD3-Gg-5AJ"/>
191
+                                            </connections>
192
+                                        </menuItem>
193
+                                        <menuItem title="Find Next" tag="2" keyEquivalent="g" id="q09-fT-Sye">
194
+                                            <connections>
195
+                                                <action selector="performFindPanelAction:" target="-1" id="NDo-RZ-v9R"/>
196
+                                            </connections>
197
+                                        </menuItem>
198
+                                        <menuItem title="Find Previous" tag="3" keyEquivalent="G" id="OwM-mh-QMV">
199
+                                            <connections>
200
+                                                <action selector="performFindPanelAction:" target="-1" id="HOh-sY-3ay"/>
201
+                                            </connections>
202
+                                        </menuItem>
203
+                                        <menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="buJ-ug-pKt">
204
+                                            <connections>
205
+                                                <action selector="performFindPanelAction:" target="-1" id="U76-nv-p5D"/>
206
+                                            </connections>
207
+                                        </menuItem>
208
+                                        <menuItem title="Jump to Selection" keyEquivalent="j" id="S0p-oC-mLd">
209
+                                            <connections>
210
+                                                <action selector="centerSelectionInVisibleArea:" target="-1" id="IOG-6D-g5B"/>
211
+                                            </connections>
212
+                                        </menuItem>
213
+                                    </items>
214
+                                </menu>
215
+                            </menuItem>
216
+                            <menuItem title="Spelling and Grammar" id="Dv1-io-Yv7">
217
+                                <modifierMask key="keyEquivalentModifierMask"/>
218
+                                <menu key="submenu" title="Spelling" id="3IN-sU-3Bg">
219
+                                    <items>
220
+                                        <menuItem title="Show Spelling and Grammar" keyEquivalent=":" id="HFo-cy-zxI">
221
+                                            <connections>
222
+                                                <action selector="showGuessPanel:" target="-1" id="vFj-Ks-hy3"/>
223
+                                            </connections>
224
+                                        </menuItem>
225
+                                        <menuItem title="Check Document Now" keyEquivalent=";" id="hz2-CU-CR7">
226
+                                            <connections>
227
+                                                <action selector="checkSpelling:" target="-1" id="fz7-VC-reM"/>
228
+                                            </connections>
229
+                                        </menuItem>
230
+                                        <menuItem isSeparatorItem="YES" id="bNw-od-mp5"/>
231
+                                        <menuItem title="Check Spelling While Typing" id="rbD-Rh-wIN">
232
+                                            <modifierMask key="keyEquivalentModifierMask"/>
233
+                                            <connections>
234
+                                                <action selector="toggleContinuousSpellChecking:" target="-1" id="7w6-Qz-0kB"/>
235
+                                            </connections>
236
+                                        </menuItem>
237
+                                        <menuItem title="Check Grammar With Spelling" id="mK6-2p-4JG">
238
+                                            <modifierMask key="keyEquivalentModifierMask"/>
239
+                                            <connections>
240
+                                                <action selector="toggleGrammarChecking:" target="-1" id="muD-Qn-j4w"/>
241
+                                            </connections>
242
+                                        </menuItem>
243
+                                        <menuItem title="Correct Spelling Automatically" id="78Y-hA-62v">
244
+                                            <modifierMask key="keyEquivalentModifierMask"/>
245
+                                            <connections>
246
+                                                <action selector="toggleAutomaticSpellingCorrection:" target="-1" id="2lM-Qi-WAP"/>
247
+                                            </connections>
248
+                                        </menuItem>
249
+                                    </items>
250
+                                </menu>
251
+                            </menuItem>
252
+                            <menuItem title="Substitutions" id="9ic-FL-obx">
253
+                                <modifierMask key="keyEquivalentModifierMask"/>
254
+                                <menu key="submenu" title="Substitutions" id="FeM-D8-WVr">
255
+                                    <items>
256
+                                        <menuItem title="Show Substitutions" id="z6F-FW-3nz">
257
+                                            <modifierMask key="keyEquivalentModifierMask"/>
258
+                                            <connections>
259
+                                                <action selector="orderFrontSubstitutionsPanel:" target="-1" id="oku-mr-iSq"/>
260
+                                            </connections>
261
+                                        </menuItem>
262
+                                        <menuItem isSeparatorItem="YES" id="gPx-C9-uUO"/>
263
+                                        <menuItem title="Smart Copy/Paste" id="9yt-4B-nSM">
264
+                                            <modifierMask key="keyEquivalentModifierMask"/>
265
+                                            <connections>
266
+                                                <action selector="toggleSmartInsertDelete:" target="-1" id="3IJ-Se-DZD"/>
267
+                                            </connections>
268
+                                        </menuItem>
269
+                                        <menuItem title="Smart Quotes" id="hQb-2v-fYv">
270
+                                            <modifierMask key="keyEquivalentModifierMask"/>
271
+                                            <connections>
272
+                                                <action selector="toggleAutomaticQuoteSubstitution:" target="-1" id="ptq-xd-QOA"/>
273
+                                            </connections>
274
+                                        </menuItem>
275
+                                        <menuItem title="Smart Dashes" id="rgM-f4-ycn">
276
+                                            <modifierMask key="keyEquivalentModifierMask"/>
277
+                                            <connections>
278
+                                                <action selector="toggleAutomaticDashSubstitution:" target="-1" id="oCt-pO-9gS"/>
279
+                                            </connections>
280
+                                        </menuItem>
281
+                                        <menuItem title="Smart Links" id="cwL-P1-jid">
282
+                                            <modifierMask key="keyEquivalentModifierMask"/>
283
+                                            <connections>
284
+                                                <action selector="toggleAutomaticLinkDetection:" target="-1" id="Gip-E3-Fov"/>
285
+                                            </connections>
286
+                                        </menuItem>
287
+                                        <menuItem title="Data Detectors" id="tRr-pd-1PS">
288
+                                            <modifierMask key="keyEquivalentModifierMask"/>
289
+                                            <connections>
290
+                                                <action selector="toggleAutomaticDataDetection:" target="-1" id="R1I-Nq-Kbl"/>
291
+                                            </connections>
292
+                                        </menuItem>
293
+                                        <menuItem title="Text Replacement" id="HFQ-gK-NFA">
294
+                                            <modifierMask key="keyEquivalentModifierMask"/>
295
+                                            <connections>
296
+                                                <action selector="toggleAutomaticTextReplacement:" target="-1" id="DvP-Fe-Py6"/>
297
+                                            </connections>
298
+                                        </menuItem>
299
+                                    </items>
300
+                                </menu>
301
+                            </menuItem>
302
+                            <menuItem title="Transformations" id="2oI-Rn-ZJC">
303
+                                <modifierMask key="keyEquivalentModifierMask"/>
304
+                                <menu key="submenu" title="Transformations" id="c8a-y6-VQd">
305
+                                    <items>
306
+                                        <menuItem title="Make Upper Case" id="vmV-6d-7jI">
307
+                                            <modifierMask key="keyEquivalentModifierMask"/>
308
+                                            <connections>
309
+                                                <action selector="uppercaseWord:" target="-1" id="sPh-Tk-edu"/>
310
+                                            </connections>
311
+                                        </menuItem>
312
+                                        <menuItem title="Make Lower Case" id="d9M-CD-aMd">
313
+                                            <modifierMask key="keyEquivalentModifierMask"/>
314
+                                            <connections>
315
+                                                <action selector="lowercaseWord:" target="-1" id="iUZ-b5-hil"/>
316
+                                            </connections>
317
+                                        </menuItem>
318
+                                        <menuItem title="Capitalize" id="UEZ-Bs-lqG">
319
+                                            <modifierMask key="keyEquivalentModifierMask"/>
320
+                                            <connections>
321
+                                                <action selector="capitalizeWord:" target="-1" id="26H-TL-nsh"/>
322
+                                            </connections>
323
+                                        </menuItem>
324
+                                    </items>
325
+                                </menu>
326
+                            </menuItem>
327
+                            <menuItem title="Speech" id="xrE-MZ-jX0">
328
+                                <modifierMask key="keyEquivalentModifierMask"/>
329
+                                <menu key="submenu" title="Speech" id="3rS-ZA-NoH">
330
+                                    <items>
331
+                                        <menuItem title="Start Speaking" id="Ynk-f8-cLZ">
332
+                                            <modifierMask key="keyEquivalentModifierMask"/>
333
+                                            <connections>
334
+                                                <action selector="startSpeaking:" target="-1" id="654-Ng-kyl"/>
335
+                                            </connections>
336
+                                        </menuItem>
337
+                                        <menuItem title="Stop Speaking" id="Oyz-dy-DGm">
338
+                                            <modifierMask key="keyEquivalentModifierMask"/>
339
+                                            <connections>
340
+                                                <action selector="stopSpeaking:" target="-1" id="dX8-6p-jy9"/>
341
+                                            </connections>
342
+                                        </menuItem>
343
+                                    </items>
344
+                                </menu>
345
+                            </menuItem>
346
+                        </items>
347
+                    </menu>
348
+                </menuItem>
349
+                <menuItem title="Server" id="QfS-bt-Xt7">
350
+                    <modifierMask key="keyEquivalentModifierMask"/>
351
+                    <menu key="submenu" title="Server" id="TDC-RU-bf6">
352
+                        <items>
353
+                            <menuItem title="Connect..." keyEquivalent="k" id="Prs-yv-Qil">
354
+                                <connections>
355
+                                    <action selector="connectToServer:" target="Voe-Tx-rLC" id="bWE-BN-9ci"/>
356
+                                </connections>
357
+                            </menuItem>
358
+                        </items>
359
+                    </menu>
360
+                </menuItem>
361
+                <menuItem title="Database" id="CFg-qm-4GG">
362
+                    <modifierMask key="keyEquivalentModifierMask"/>
363
+                    <menu key="submenu" title="Database" id="nD3-Xo-LUZ">
364
+                        <items>
365
+                            <menuItem title="Run Query" id="RSP-nH-a1I">
366
+                                <string key="keyEquivalent" base64-UTF8="YES">
367
+DQ
368
+</string>
369
+                                <connections>
370
+                                    <action selector="runQuery:" target="-1" id="jLo-qu-WjN"/>
371
+                                </connections>
372
+                            </menuItem>
373
+                        </items>
374
+                    </menu>
375
+                </menuItem>
376
+                <menuItem title="View" id="H8h-7b-M4v">
377
+                    <modifierMask key="keyEquivalentModifierMask"/>
378
+                    <menu key="submenu" title="View" id="HyV-fh-RgO">
379
+                        <items>
380
+                            <menuItem title="Show Toolbar" keyEquivalent="t" id="snW-S8-Cw5">
381
+                                <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
382
+                                <connections>
383
+                                    <action selector="toggleToolbarShown:" target="-1" id="BXY-wc-z0C"/>
384
+                                </connections>
385
+                            </menuItem>
386
+                            <menuItem title="Customize Toolbar…" id="1UK-8n-QPP">
387
+                                <modifierMask key="keyEquivalentModifierMask"/>
388
+                                <connections>
389
+                                    <action selector="runToolbarCustomizationPalette:" target="-1" id="pQI-g3-MTW"/>
390
+                                </connections>
391
+                            </menuItem>
392
+                            <menuItem isSeparatorItem="YES" id="hB3-LF-h0Y"/>
393
+                            <menuItem title="Show Sidebar" keyEquivalent="s" id="kIP-vf-haE">
394
+                                <modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
395
+                                <connections>
396
+                                    <action selector="toggleSidebar:" target="-1" id="iwa-gc-5KM"/>
397
+                                </connections>
398
+                            </menuItem>
399
+                            <menuItem title="Enter Full Screen" keyEquivalent="f" id="4J7-dP-txa">
400
+                                <modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
401
+                                <connections>
402
+                                    <action selector="toggleFullScreen:" target="-1" id="dU3-MA-1Rq"/>
403
+                                </connections>
404
+                            </menuItem>
405
+                        </items>
406
+                    </menu>
407
+                </menuItem>
408
+                <menuItem title="Window" id="aUF-d1-5bR">
409
+                    <modifierMask key="keyEquivalentModifierMask"/>
410
+                    <menu key="submenu" title="Window" systemMenu="window" id="Td7-aD-5lo">
411
+                        <items>
412
+                            <menuItem title="Minimize" keyEquivalent="m" id="OY7-WF-poV">
413
+                                <connections>
414
+                                    <action selector="performMiniaturize:" target="-1" id="VwT-WD-YPe"/>
415
+                                </connections>
416
+                            </menuItem>
417
+                            <menuItem title="Zoom" id="R4o-n2-Eq4">
418
+                                <modifierMask key="keyEquivalentModifierMask"/>
419
+                                <connections>
420
+                                    <action selector="performZoom:" target="-1" id="DIl-cC-cCs"/>
421
+                                </connections>
422
+                            </menuItem>
423
+                            <menuItem isSeparatorItem="YES" id="eu3-7i-yIM"/>
424
+                            <menuItem title="Bring All to Front" id="LE2-aR-0XJ">
425
+                                <modifierMask key="keyEquivalentModifierMask"/>
426
+                                <connections>
427
+                                    <action selector="arrangeInFront:" target="-1" id="DRN-fu-gQh"/>
428
+                                </connections>
429
+                            </menuItem>
430
+                        </items>
431
+                    </menu>
432
+                </menuItem>
433
+                <menuItem title="Help" id="wpr-3q-Mcd">
434
+                    <modifierMask key="keyEquivalentModifierMask"/>
435
+                    <menu key="submenu" title="Help" systemMenu="help" id="F2S-fz-NVQ">
436
+                        <items>
437
+                            <menuItem title="MongoView Help" keyEquivalent="?" id="FKE-Sm-Kum">
438
+                                <connections>
439
+                                    <action selector="showHelp:" target="-1" id="y7X-2Q-9no"/>
440
+                                </connections>
441
+                            </menuItem>
442
+                        </items>
443
+                    </menu>
444
+                </menuItem>
445
+            </items>
446
+            <point key="canvasLocation" x="141" y="154"/>
447
+        </menu>
448
+    </objects>
449
+</document>

+ 36
- 0
MongoView/Info.plist View File

@@ -0,0 +1,36 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+<plist version="1.0">
4
+<dict>
5
+	<key>CFBundleDevelopmentRegion</key>
6
+	<string>$(DEVELOPMENT_LANGUAGE)</string>
7
+	<key>CFBundleExecutable</key>
8
+	<string>$(EXECUTABLE_NAME)</string>
9
+	<key>CFBundleIconFile</key>
10
+	<string></string>
11
+	<key>CFBundleIdentifier</key>
12
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
13
+	<key>CFBundleInfoDictionaryVersion</key>
14
+	<string>6.0</string>
15
+	<key>CFBundleName</key>
16
+	<string>$(PRODUCT_NAME)</string>
17
+	<key>CFBundlePackageType</key>
18
+	<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
19
+	<key>CFBundleShortVersionString</key>
20
+	<string>1.0</string>
21
+	<key>CFBundleVersion</key>
22
+	<string>1</string>
23
+	<key>LSMinimumSystemVersion</key>
24
+	<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
25
+	<key>NSHumanReadableCopyright</key>
26
+	<string>Copyright © 2020 Shadowfacts. All rights reserved.</string>
27
+	<key>NSMainNibFile</key>
28
+	<string>MainMenu</string>
29
+	<key>NSPrincipalClass</key>
30
+	<string>NSApplication</string>
31
+	<key>NSSupportsAutomaticTermination</key>
32
+	<true/>
33
+	<key>NSSupportsSuddenTermination</key>
34
+	<true/>
35
+</dict>
36
+</plist>

+ 37
- 0
MongoView/MongoController.swift View File

@@ -0,0 +1,37 @@
1
+//
2
+//  MongoController.swift
3
+//  MongoView
4
+//
5
+//  Created by Shadowfacts on 1/8/20.
6
+//  Copyright © 2020 Shadowfacts. All rights reserved.
7
+//
8
+
9
+import Foundation
10
+import MongoSwift
11
+import NIO
12
+
13
+class MongoController {
14
+    let connectionString: String
15
+    
16
+    var group: EventLoopGroup!
17
+    
18
+    var client: MongoClient!
19
+
20
+    init(connectionString: String) {
21
+        self.connectionString = connectionString
22
+    }
23
+    
24
+    deinit {
25
+        try! group.syncShutdownGracefully()
26
+        cleanupMongoSwift()
27
+    }
28
+    
29
+    func setup() {
30
+        print("setting up mongo")
31
+        
32
+        group = MultiThreadedEventLoopGroup(numberOfThreads: 1)
33
+        
34
+        client = try! MongoClient(connectionString, using: group)
35
+    }
36
+
37
+}

+ 12
- 0
MongoView/MongoView.entitlements View File

@@ -0,0 +1,12 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+<plist version="1.0">
4
+<dict>
5
+	<key>com.apple.security.app-sandbox</key>
6
+	<true/>
7
+	<key>com.apple.security.files.user-selected.read-only</key>
8
+	<true/>
9
+	<key>com.apple.security.network.client</key>
10
+	<true/>
11
+</dict>
12
+</plist>

+ 146
- 0
MongoView/Node.swift View File

@@ -0,0 +1,146 @@
1
+//
2
+//  Node.swift
3
+//  MongoView
4
+//
5
+//  Created by Shadowfacts on 1/9/20.
6
+//  Copyright © 2020 Shadowfacts. All rights reserved.
7
+//
8
+
9
+import Foundation
10
+import MongoSwift
11
+
12
+class Node {
13
+    let key: Key?
14
+    let value: BSON
15
+    
16
+    lazy private(set) var children: [Node] = {
17
+        switch value {
18
+        case let .array(array):
19
+            return array.enumerated().map { (index, val) in
20
+                Node(key: .index(index), value: val)
21
+            }
22
+        case let .document(doc):
23
+            return doc.map { (key, val) in
24
+                Node(key: .name(key), value: val)
25
+            }
26
+        default:
27
+            return []
28
+        }
29
+    }()
30
+    
31
+    var numberOfChildren: Int {
32
+        children.count
33
+    }
34
+    
35
+    var hasChildren: Bool {
36
+        numberOfChildren > 0
37
+    }
38
+
39
+    init(key: Key? = nil, value: BSON) {
40
+        self.key = key
41
+        self.value = value
42
+    }
43
+    
44
+    convenience init(document: Document) {
45
+        if case let .objectId(id) = document["_id"] {
46
+            self.init(key: .objectId(id), value: .document(document))
47
+        } else {
48
+            self.init(key: nil, value: .document(document))
49
+        }
50
+    }
51
+}
52
+
53
+extension Node {
54
+    enum Key {
55
+        case index(Int)
56
+        case name(String)
57
+        case objectId(ObjectId)
58
+    }
59
+}
60
+
61
+extension Node {
62
+    static let dateFormatter: DateFormatter = {
63
+        let formatter = DateFormatter()
64
+        formatter.locale = .current
65
+        formatter.setLocalizedDateFormatFromTemplate("yyyy-MM-dd HH:mm:ss ZZ")
66
+        return formatter
67
+    }()
68
+    
69
+    var keyString: String {
70
+        switch key {
71
+        case nil:
72
+            return ""
73
+        case let .index(index):
74
+            return index.description
75
+        case let .name(name):
76
+            return name
77
+        case let .objectId(id):
78
+            return id.description
79
+        }
80
+    }
81
+    
82
+    var valueString: String {
83
+        switch value {
84
+        case let .double(value):
85
+            return value.description
86
+        case let .string(value):
87
+            return value
88
+        case let .document(doc):
89
+            return "(\(doc.count) field\(doc.count == 1 ? "" : "s"))"
90
+        case let .array(array):
91
+            return "(\(array.count) element\(array.count == 1 ? "" : "s"))"
92
+        case let .binary(value):
93
+            switch Binary.Subtype(rawValue: value.subtype) {
94
+            case nil:
95
+                return "(unknown binary data)"
96
+            case .generic:
97
+                return "(generic binary data)"
98
+            case .function:
99
+                return "(function binary data)"
100
+            case .binaryDeprecated:
101
+                return "(binary data)"
102
+            case .uuidDeprecated:
103
+                fallthrough
104
+            case .uuid:
105
+                return try! UUID(from: value).description
106
+            case .md5:
107
+                return "(MD5 binary data)"
108
+            case .userDefined:
109
+                return "(user defined binary data)"
110
+            }
111
+        case .undefined:
112
+            return "undefined"
113
+        case let .objectId(value):
114
+            return value.description
115
+        case let .bool(value):
116
+            return value.description
117
+        case let .datetime(value):
118
+            return value.description
119
+        case .null:
120
+            return "null"
121
+        case let .regex(value):
122
+            return try! NSRegularExpression(from: value).description
123
+        case let .dbPointer(value):
124
+            return "\(value.ref)(\(value.id))"
125
+        case let .symbol(value):
126
+            return value.description
127
+        case let .code(value):
128
+            return value.code
129
+        case let .codeWithScope(value):
130
+            return value.code
131
+        case let .int32(value):
132
+            return value.description
133
+        case let .timestamp(value):
134
+            let date = Date(timeIntervalSince1970: TimeInterval(value.timestamp))
135
+            return Node.dateFormatter.string(from: date)
136
+        case let .int64(value):
137
+            return value.description
138
+        case let .decimal128(value):
139
+            return value.description
140
+        case .minKey:
141
+            return "(min key)"
142
+        case .maxKey:
143
+            return "(max key)"
144
+        }
145
+    }
146
+}

+ 214
- 0
MongoView/View Controllers/DatabaseViewController.swift View File

@@ -0,0 +1,214 @@
1
+//
2
+//  DatabaseViewController.swift
3
+//  MongoView
4
+//
5
+//  Created by Shadowfacts on 1/10/20.
6
+//  Copyright © 2020 Shadowfacts. All rights reserved.
7
+//
8
+
9
+import Cocoa
10
+import MongoSwift
11
+import NIO
12
+
13
+struct DatabaseCollections {
14
+    let database: String
15
+    let collections: [String]
16
+}
17
+
18
+struct DatabaseCollection {
19
+    let database: String
20
+    let name: String
21
+}
22
+
23
+class DatabaseViewController: NSViewController {
24
+    
25
+    @IBOutlet weak var collectionsOutlineView: NSOutlineView!
26
+    @IBOutlet weak var detailContainerView: NSView!
27
+    
28
+    let mongoController: MongoController
29
+    
30
+    private var databaseCollections: [DatabaseCollections] = []
31
+    private var selectedCollection: DatabaseCollection?
32
+
33
+    private var placeholderLabel: NSTextField?
34
+    private var queryViewController: QueryViewController?
35
+    
36
+    init(mongoController: MongoController) {
37
+        self.mongoController = mongoController
38
+        
39
+        super.init(nibName: "DatabaseViewController", bundle: .main)
40
+    }
41
+    
42
+    required init?(coder: NSCoder) {
43
+        fatalError("init(coder:) has not been implemented")
44
+    }
45
+    
46
+    override func viewDidLoad() {
47
+        super.viewDidLoad()
48
+        
49
+        mongoController.client.listDatabaseNames().flatMap { (databaseNames) -> EventLoopFuture<[DatabaseCollections]> in
50
+            let futures = databaseNames.map { (name) in
51
+                self.mongoController.client.db(name).listCollectionNames().map { (collectionNames) in
52
+                    DatabaseCollections(database: name, collections: collectionNames)
53
+                }
54
+            }
55
+            return EventLoopFuture.whenAllSucceed(futures, on: futures.first!.eventLoop)
56
+        }.whenComplete { [weak self] (res) in
57
+            guard let self = self else { return }
58
+            
59
+            switch res {
60
+            case let .success(databaseCollections):
61
+                self.databaseCollections = databaseCollections
62
+                DispatchQueue.main.async {
63
+                    self.collectionsOutlineView.reloadData()
64
+                }
65
+                
66
+            case let .failure(error):
67
+                fatalError("error getting database names: \(error)")
68
+            }
69
+        }
70
+
71
+        collectionsOutlineView.dataSource = self
72
+        collectionsOutlineView.delegate = self
73
+        
74
+        collectionsOutlineView.target = self
75
+        collectionsOutlineView.doubleAction = #selector(cellDoubleClicked)
76
+        
77
+        updateDetailView()
78
+    }
79
+    
80
+    func showCollection(_ collection: DatabaseCollection) {
81
+        selectedCollection = collection
82
+        updateDetailView()
83
+    }
84
+    
85
+    private func updateDetailView() {
86
+        if let collection = selectedCollection {
87
+            if let placeholderLabel = placeholderLabel {
88
+                placeholderLabel.removeFromSuperview()
89
+            }
90
+            if let oldQueryViewController = self.queryViewController {
91
+                oldQueryViewController.view.removeFromSuperview()
92
+                oldQueryViewController.removeFromParent()
93
+            }
94
+            
95
+            let queryViewController = QueryViewController(mongoController: mongoController, collection: collection)
96
+            self.queryViewController = queryViewController
97
+            queryViewController.view.translatesAutoresizingMaskIntoConstraints = false
98
+            addChild(queryViewController)
99
+            detailContainerView.addSubview(queryViewController.view)
100
+            NSLayoutConstraint.activate([
101
+                queryViewController.view.leadingAnchor.constraint(equalTo: detailContainerView.leadingAnchor),
102
+                queryViewController.view.trailingAnchor.constraint(equalTo: detailContainerView.trailingAnchor),
103
+                queryViewController.view.topAnchor.constraint(equalTo: detailContainerView.topAnchor),
104
+                queryViewController.view.bottomAnchor.constraint(equalTo: detailContainerView.bottomAnchor)
105
+            ])
106
+            
107
+            self.title = queryViewController.title
108
+        } else {
109
+            if let queryViewController = queryViewController {
110
+                queryViewController.view.removeFromSuperview()
111
+                queryViewController.removeFromParent()
112
+            }
113
+            
114
+            if self.placeholderLabel == nil {
115
+                let label = NSTextField(labelWithString: "Select a collection to begin")
116
+                self.placeholderLabel = label
117
+                label.translatesAutoresizingMaskIntoConstraints = false
118
+                detailContainerView.addSubview(label)
119
+                NSLayoutConstraint.activate([
120
+                    label.centerXAnchor.constraint(equalTo: detailContainerView.centerXAnchor),
121
+                    label.centerYAnchor.constraint(equalTo: detailContainerView.centerYAnchor)
122
+                ])
123
+    
124
+                self.title = "No Query"
125
+            }
126
+        }
127
+    }
128
+    
129
+    @objc func cellDoubleClicked() {
130
+        let item = collectionsOutlineView.item(atRow: collectionsOutlineView.clickedRow)!
131
+        
132
+        if item is DatabaseCollections {
133
+            if collectionsOutlineView.isItemExpanded(item) {
134
+                collectionsOutlineView.collapseItem(item)
135
+            } else {
136
+                collectionsOutlineView.expandItem(item)
137
+            }
138
+        } else if let collection = item as? DatabaseCollection {
139
+            // only open a new window/tab if our own query has changed from the default, otherwise replace our query controller
140
+            if let queryViewController = queryViewController, queryViewController.hasQueryChanged {
141
+                (NSApplication.shared.delegate as! AppDelegate).newWindow(mongoController: mongoController, collection: collection)
142
+            } else {
143
+                self.selectedCollection = collection
144
+                updateDetailView()
145
+            }
146
+        }
147
+    }
148
+
149
+    @IBAction func runQuery(_ sender: Any) {
150
+        guard let queryViewController = queryViewController else {
151
+            return
152
+        }
153
+        queryViewController.runQuery()
154
+    }
155
+}
156
+
157
+extension DatabaseViewController: NSMenuItemValidation {
158
+    func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
159
+        if menuItem.action == #selector(runQuery(_:)) {
160
+            return queryViewController != nil
161
+        }
162
+        return true
163
+    }
164
+}
165
+
166
+extension DatabaseViewController: NSOutlineViewDataSource {
167
+    func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int {
168
+        if item == nil {
169
+            return databaseCollections.count
170
+        } else if let database = item as? DatabaseCollections {
171
+            return database.collections.count
172
+        } else {
173
+            return 0
174
+        }
175
+    }
176
+    
177
+    func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool {
178
+        return item is DatabaseCollections
179
+    }
180
+    
181
+    func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any {
182
+        if item == nil {
183
+            return databaseCollections[index]
184
+        } else if let databaseCollections = item as? DatabaseCollections {
185
+            let collection = databaseCollections.collections[index]
186
+            return DatabaseCollection(database: databaseCollections.database, name: collection)
187
+        } else {
188
+            fatalError()
189
+        }
190
+    }
191
+}
192
+
193
+extension DatabaseViewController: NSOutlineViewDelegate {
194
+    func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? {
195
+        if let database = item as? DatabaseCollections {
196
+            let cell = outlineView.makeView(withIdentifier: .databaseNameCell, owner: nil) as! NSTableCellView
197
+            cell.textField!.stringValue = database.database
198
+            cell.textField!.isEditable = false
199
+            return cell
200
+        } else if let collection = item as? DatabaseCollection {
201
+            let cell = outlineView.makeView(withIdentifier: .collectionNameCell, owner: nil) as! NSTableCellView
202
+            cell.textField!.stringValue = collection.name
203
+            cell.textField!.isEditable = false
204
+            return cell
205
+        } else {
206
+            fatalError()
207
+        }
208
+    }
209
+}
210
+
211
+extension NSUserInterfaceItemIdentifier {
212
+    static let databaseNameCell = NSUserInterfaceItemIdentifier(rawValue: "DatabaseNameCell")
213
+    static let collectionNameCell = NSUserInterfaceItemIdentifier(rawValue: "CollectionNameCell")
214
+}

+ 143
- 0
MongoView/View Controllers/DatabaseViewController.xib View File

@@ -0,0 +1,143 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="15702" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
3
+    <dependencies>
4
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15702"/>
5
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
6
+    </dependencies>
7
+    <objects>
8
+        <customObject id="-2" userLabel="File's Owner" customClass="DatabaseViewController" customModule="MongoView" customModuleProvider="target">
9
+            <connections>
10
+                <outlet property="collectionsOutlineView" destination="V8b-zo-g9y" id="MHN-98-SLo"/>
11
+                <outlet property="detailContainerView" destination="XEU-4D-Mdl" id="TwG-BX-2Gv"/>
12
+                <outlet property="view" destination="Hz6-mo-xeY" id="0bl-1N-x8E"/>
13
+            </connections>
14
+        </customObject>
15
+        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
16
+        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
17
+        <customView id="Hz6-mo-xeY">
18
+            <rect key="frame" x="0.0" y="0.0" width="963" height="618"/>
19
+            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
20
+            <subviews>
21
+                <splitView arrangesAllSubviews="NO" dividerStyle="thin" vertical="YES" translatesAutoresizingMaskIntoConstraints="NO" id="5Fg-Gm-qda">
22
+                    <rect key="frame" x="0.0" y="0.0" width="963" height="618"/>
23
+                    <subviews>
24
+                        <customView id="oWj-Ph-gg6">
25
+                            <rect key="frame" x="0.0" y="0.0" width="258" height="618"/>
26
+                            <autoresizingMask key="autoresizingMask"/>
27
+                            <subviews>
28
+                                <scrollView autohidesScrollers="YES" horizontalLineScroll="19" horizontalPageScroll="10" verticalLineScroll="19" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="h6f-Xn-ruZ">
29
+                                    <rect key="frame" x="0.0" y="0.0" width="258" height="618"/>
30
+                                    <clipView key="contentView" drawsBackground="NO" id="x7X-dI-jkR">
31
+                                        <rect key="frame" x="1" y="1" width="256" height="616"/>
32
+                                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
33
+                                        <subviews>
34
+                                            <outlineView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" selectionHighlightStyle="sourceList" multipleSelection="NO" autosaveColumns="NO" rowSizeStyle="automatic" viewBased="YES" indentationPerLevel="16" outlineTableColumn="jbA-H8-mVM" id="V8b-zo-g9y">
35
+                                                <rect key="frame" x="0.0" y="0.0" width="256" height="616"/>
36
+                                                <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
37
+                                                <size key="intercellSpacing" width="3" height="2"/>
38
+                                                <color key="backgroundColor" name="_sourceListBackgroundColor" catalog="System" colorSpace="catalog"/>
39
+                                                <color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
40
+                                                <tableColumns>
41
+                                                    <tableColumn width="253" minWidth="16" maxWidth="1000" id="jbA-H8-mVM">
42
+                                                        <tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border">
43
+                                                            <font key="font" metaFont="label" size="11"/>
44
+                                                            <color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
45
+                                                            <color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
46
+                                                        </tableHeaderCell>
47
+                                                        <textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" title="Text Cell" id="xnp-1R-i8D">
48
+                                                            <font key="font" metaFont="system"/>
49
+                                                            <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
50
+                                                            <color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
51
+                                                        </textFieldCell>
52
+                                                        <tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
53
+                                                        <prototypeCellViews>
54
+                                                            <tableCellView identifier="DatabaseNameCell" id="rKw-cV-n1d">
55
+                                                                <rect key="frame" x="1" y="1" width="253" height="17"/>
56
+                                                                <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
57
+                                                                <subviews>
58
+                                                                    <textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="FFr-3D-mui">
59
+                                                                        <rect key="frame" x="0.0" y="1" width="253" height="14"/>
60
+                                                                        <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
61
+                                                                        <textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="HEADER CELL" id="cEl-mJ-9oh">
62
+                                                                            <font key="font" metaFont="smallSystemBold"/>
63
+                                                                            <color key="textColor" name="headerColor" catalog="System" colorSpace="catalog"/>
64
+                                                                            <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
65
+                                                                        </textFieldCell>
66
+                                                                    </textField>
67
+                                                                </subviews>
68
+                                                                <connections>
69
+                                                                    <outlet property="textField" destination="FFr-3D-mui" id="5i3-fV-eYZ"/>
70
+                                                                </connections>
71
+                                                            </tableCellView>
72
+                                                            <tableCellView identifier="CollectionNameCell" id="hIt-06-qWa">
73
+                                                                <rect key="frame" x="1" y="20" width="253" height="17"/>
74
+                                                                <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
75
+                                                                <subviews>
76
+                                                                    <imageView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ccM-b1-d7j">
77
+                                                                        <rect key="frame" x="3" y="0.0" width="17" height="17"/>
78
+                                                                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
79
+                                                                        <imageCell key="cell" refusesFirstResponder="YES" imageScaling="proportionallyDown" image="NSActionTemplate" id="kCZ-pa-Nqs"/>
80
+                                                                    </imageView>
81
+                                                                    <textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Lxc-CX-ZCN">
82
+                                                                        <rect key="frame" x="25" y="0.0" width="228" height="17"/>
83
+                                                                        <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
84
+                                                                        <textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="5CJ-WG-qTe">
85
+                                                                            <font key="font" metaFont="system"/>
86
+                                                                            <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
87
+                                                                            <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
88
+                                                                        </textFieldCell>
89
+                                                                    </textField>
90
+                                                                </subviews>
91
+                                                                <connections>
92
+                                                                    <outlet property="imageView" destination="ccM-b1-d7j" id="otw-h0-Zyz"/>
93
+                                                                    <outlet property="textField" destination="Lxc-CX-ZCN" id="cW2-4u-Tl2"/>
94
+                                                                </connections>
95
+                                                            </tableCellView>
96
+                                                        </prototypeCellViews>
97
+                                                    </tableColumn>
98
+                                                </tableColumns>
99
+                                            </outlineView>
100
+                                        </subviews>
101
+                                        <nil key="backgroundColor"/>
102
+                                    </clipView>
103
+                                    <scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="all-QE-bCD">
104
+                                        <rect key="frame" x="1" y="119" width="238" height="15"/>
105
+                                        <autoresizingMask key="autoresizingMask"/>
106
+                                    </scroller>
107
+                                    <scroller key="verticalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="x72-Cx-DrL">
108
+                                        <rect key="frame" x="224" y="17" width="15" height="102"/>
109
+                                        <autoresizingMask key="autoresizingMask"/>
110
+                                    </scroller>
111
+                                </scrollView>
112
+                            </subviews>
113
+                            <constraints>
114
+                                <constraint firstAttribute="trailing" secondItem="h6f-Xn-ruZ" secondAttribute="trailing" id="CYf-mb-0kx"/>
115
+                                <constraint firstItem="h6f-Xn-ruZ" firstAttribute="top" secondItem="oWj-Ph-gg6" secondAttribute="top" id="OHe-aL-LhC"/>
116
+                                <constraint firstItem="h6f-Xn-ruZ" firstAttribute="leading" secondItem="oWj-Ph-gg6" secondAttribute="leading" id="d9N-28-6qQ"/>
117
+                                <constraint firstAttribute="bottom" secondItem="h6f-Xn-ruZ" secondAttribute="bottom" id="fmp-A8-teG"/>
118
+                            </constraints>
119
+                        </customView>
120
+                        <customView fixedFrame="YES" id="XEU-4D-Mdl">
121
+                            <rect key="frame" x="259" y="0.0" width="704" height="618"/>
122
+                            <autoresizingMask key="autoresizingMask"/>
123
+                        </customView>
124
+                    </subviews>
125
+                    <holdingPriorities>
126
+                        <real value="250"/>
127
+                        <real value="250"/>
128
+                    </holdingPriorities>
129
+                </splitView>
130
+            </subviews>
131
+            <constraints>
132
+                <constraint firstItem="5Fg-Gm-qda" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" id="HRn-8t-EI3"/>
133
+                <constraint firstItem="5Fg-Gm-qda" firstAttribute="top" secondItem="Hz6-mo-xeY" secondAttribute="top" id="Tco-te-GLJ"/>
134
+                <constraint firstAttribute="trailing" secondItem="5Fg-Gm-qda" secondAttribute="trailing" id="f5N-wp-15r"/>
135
+                <constraint firstAttribute="bottom" secondItem="5Fg-Gm-qda" secondAttribute="bottom" id="l7G-Jh-PBe"/>
136
+            </constraints>
137
+            <point key="canvasLocation" x="-8.5" y="361"/>
138
+        </customView>
139
+    </objects>
140
+    <resources>
141
+        <image name="NSActionTemplate" width="14" height="14"/>
142
+    </resources>
143
+</document>

+ 166
- 0
MongoView/View Controllers/QueryViewController.swift View File

@@ -0,0 +1,166 @@
1
+//
2
+//  QueryViewController.swift
3
+//  MongoView
4
+//
5
+//  Created by Shadowfacts on 1/9/20.
6
+//  Copyright © 2020 Shadowfacts. All rights reserved.
7
+//
8
+
9
+import Cocoa
10
+import MongoSwift
11
+
12
+class QueryViewController: NSViewController {
13
+
14
+    @IBOutlet weak var verticalSplitView: NSSplitView!
15
+    @IBOutlet var queryTextView: NSTextView!
16
+    @IBOutlet weak var outlineView: NSOutlineView!
17
+    @IBOutlet weak var documentCountLabel: NSTextField!
18
+    
19
+    let mongoController: MongoController
20
+    let collection: DatabaseCollection
21
+    
22
+    var defaultQuery: String {
23
+        "db.getCollection('\(collection.name)').find({})"
24
+    }
25
+    
26
+    var hasQueryChanged: Bool {
27
+        return queryTextView.string != defaultQuery
28
+    }
29
+    
30
+    var rootNodes: [Node] = []
31
+    
32
+    init(mongoController: MongoController, collection: DatabaseCollection) {
33
+        self.mongoController = mongoController
34
+        self.collection = collection
35
+        
36
+        super.init(nibName: "QueryViewController", bundle: .main)
37
+    }
38
+    
39
+    required init?(coder: NSCoder) {
40
+        fatalError("init(coder:) has not been implemented")
41
+    }
42
+    
43
+    override func viewDidLoad() {
44
+        super.viewDidLoad()
45
+        
46
+        let db = mongoController.client.db(collection.database)
47
+        let collection = db.collection(self.collection.name)
48
+        let documents = try! collection.find().all()
49
+        rootNodes = documents.map { Node(document: $0) }
50
+        
51
+        verticalSplitView.delegate = self
52
+        verticalSplitView.setHoldingPriority(.defaultHigh, forSubviewAt: 0)
53
+        
54
+        queryTextView.font = .monospacedSystemFont(ofSize: 13, weight: .regular)
55
+        queryTextView.isAutomaticQuoteSubstitutionEnabled = false
56
+        queryTextView.string = defaultQuery
57
+        
58
+        outlineView.dataSource = self
59
+        outlineView.delegate = self
60
+        
61
+        outlineView.target = self
62
+        outlineView.doubleAction = #selector(outlineCellDoubleClicked)
63
+        
64
+        title = "\(self.collection.database).\(self.collection.name)"
65
+
66
+        documentCountLabel.stringValue = "\(documents.count) document\(documents.count == 1 ? "" : "s")"
67
+    }
68
+    
69
+    override func viewWillAppear() {
70
+        super.viewWillAppear()
71
+        
72
+        verticalSplitView.setPosition(80, ofDividerAt: 0)
73
+
74
+    }
75
+    
76
+    override func viewDidAppear() {
77
+        super.viewDidAppear()
78
+        
79
+        
80
+        view.window!.makeFirstResponder(outlineView)
81
+    }
82
+    
83
+    func runQuery() {
84
+        print("run query: \(queryTextView.string)")
85
+//        mongoController.db.runCommand(["eval": .code(Code(code: queryTextView.string))]).whenComplete { (res) in
86
+//            print(res)
87
+//        }
88
+    }
89
+    
90
+    @objc func outlineCellDoubleClicked() {
91
+        if let item = outlineView.item(atRow: outlineView.clickedRow) {
92
+            if outlineView.isItemExpanded(item) {
93
+                outlineView.collapseItem(item)
94
+            } else {
95
+                outlineView.expandItem(item)
96
+            }
97
+        }
98
+    }
99
+    
100
+}
101
+
102
+extension QueryViewController: NSSplitViewDelegate {
103
+    func splitView(_ splitView: NSSplitView, constrainSplitPosition proposedPosition: CGFloat, ofSubviewAt dividerIndex: Int) -> CGFloat {
104
+        return max(80, min(splitView.bounds.height / 2, proposedPosition))
105
+    }
106
+}
107
+
108
+extension QueryViewController: NSOutlineViewDataSource {
109
+    func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int {
110
+        if item == nil {
111
+            return rootNodes.count
112
+        } else if let node = item as? Node {
113
+            return node.numberOfChildren
114
+        } else {
115
+            return 0
116
+        }
117
+    }
118
+    
119
+    func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool {
120
+        if let node = item as? Node {
121
+            return node.hasChildren
122
+        } else {
123
+            return false
124
+        }
125
+    }
126
+    
127
+    func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any {
128
+        if item == nil {
129
+            return rootNodes[index]
130
+        } else if let node = item as? Node {
131
+            return node.children[index]
132
+        } else {
133
+            fatalError("unreachable")
134
+        }
135
+    }
136
+}
137
+
138
+extension QueryViewController: NSOutlineViewDelegate {
139
+    func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? {
140
+        guard let tableColumn = tableColumn,
141
+            let node = item as? Node else {
142
+                fatalError()
143
+        }
144
+        if tableColumn.identifier == .fieldNameColumn {
145
+            let cell = outlineView.makeView(withIdentifier: .fieldNameCell, owner: nil) as! NSTableCellView
146
+            cell.textField!.stringValue = node.keyString
147
+            cell.textField!.isEditable = false
148
+            return cell
149
+        } else if tableColumn.identifier == .fieldValueColumn {
150
+            let cell = outlineView.makeView(withIdentifier: .fieldValueCell, owner: nil) as! NSTableCellView
151
+            cell.textField!.stringValue = node.valueString
152
+            cell.textField!.isEditable = false
153
+            return cell
154
+        } else {
155
+            return nil
156
+        }
157
+    }
158
+}
159
+
160
+
161
+extension NSUserInterfaceItemIdentifier {
162
+    static let fieldNameColumn = NSUserInterfaceItemIdentifier(rawValue: "FieldNameCol")
163
+    static let fieldValueColumn = NSUserInterfaceItemIdentifier(rawValue: "FieldValueCol")
164
+    static let fieldNameCell = NSUserInterfaceItemIdentifier(rawValue: "FieldNameCell")
165
+    static let fieldValueCell = NSUserInterfaceItemIdentifier(rawValue: "FieldValueCell")
166
+}

+ 1108
- 0
MongoView/View Controllers/QueryViewController.xib
File diff suppressed because it is too large
View File


+ 89
- 0
MongoView/View Controllers/ServerConnectViewController.swift View File

@@ -0,0 +1,89 @@
1
+//
2
+//  ServerConnectViewController.swift
3
+//  MongoView
4
+//
5
+//  Created by Shadowfacts on 1/11/20.
6
+//  Copyright © 2020 Shadowfacts. All rights reserved.
7
+//
8
+
9
+import Cocoa
10
+
11
+protocol ServerConnectViewControllerDelegate: class {
12
+    func connectToServer(mongoController: MongoController)
13
+}
14
+
15
+class ServerConnectViewController: NSViewController {
16
+    
17
+    weak var delegate: ServerConnectViewControllerDelegate?
18
+
19
+    @IBOutlet weak var hostTextField: NSTextField!
20
+    @IBOutlet weak var portTextField: NSTextField!
21
+    @IBOutlet weak var usernameTextField: NSTextField!
22
+    @IBOutlet weak var passwordTextField: NSSecureTextField!
23
+    @IBOutlet weak var connectButton: NSButton!
24
+    
25
+    init() {
26
+        super.init(nibName: "ServerConnectViewController", bundle: .main)
27
+    }
28
+    
29
+    required init?(coder: NSCoder) {
30
+        fatalError("init(coder:) has not been implemented")
31
+    }
32
+    
33
+    override func viewDidLoad() {
34
+        super.viewDidLoad()
35
+        
36
+        hostTextField.delegate = self
37
+        portTextField.delegate = self
38
+        
39
+        hostTextField.nextKeyView = portTextField
40
+        portTextField.nextKeyView = usernameTextField
41
+        usernameTextField.nextKeyView = passwordTextField
42
+        passwordTextField.nextKeyView = hostTextField
43
+        
44
+        updateConnectButtonEnabled()
45
+    }
46
+    
47
+    override func viewWillAppear() {
48
+        super.viewWillAppear()
49
+        
50
+        view.window!.initialFirstResponder = hostTextField
51
+    }
52
+    
53
+    func updateConnectButtonEnabled() {
54
+        connectButton.isEnabled = !hostTextField.stringValue.isEmpty && !portTextField.stringValue.isEmpty
55
+    }
56
+    
57
+    @IBAction func connect(_ sender: Any) {
58
+        connectButton.isEnabled = false
59
+        hostTextField.isEnabled = false
60
+        portTextField.isEnabled = false
61
+        usernameTextField.isEnabled = false
62
+        passwordTextField.isEnabled = false
63
+        
64
+        var str = "mongodb://"
65
+        if !usernameTextField.stringValue.isEmpty {
66
+            str += usernameTextField.stringValue
67
+            if !passwordTextField.stringValue.isEmpty {
68
+                str.append(":")
69
+                str.append(passwordTextField.stringValue)
70
+            }
71
+            str.append("@")
72
+        }
73
+        str.append(hostTextField.stringValue)
74
+        str.append(":")
75
+        str.append(portTextField.stringValue)
76
+
77
+        let mongoController = MongoController(connectionString: str)
78
+        mongoController.setup()
79
+        
80
+        delegate?.connectToServer(mongoController: mongoController)
81
+    }
82
+    
83
+}
84
+
85
+extension ServerConnectViewController: NSTextFieldDelegate {
86
+    func controlTextDidChange(_ obj: Notification) {
87
+        updateConnectButtonEnabled()
88
+    }
89
+}

+ 212
- 0
MongoView/View Controllers/ServerConnectViewController.xib View File

@@ -0,0 +1,212 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="15702" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
3
+    <dependencies>
4
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15702"/>
5
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
6
+    </dependencies>
7
+    <objects>
8
+        <customObject id="-2" userLabel="File's Owner" customClass="ServerConnectViewController" customModule="MongoView" customModuleProvider="target">
9
+            <connections>
10
+                <outlet property="connectButton" destination="uoF-7g-BAZ" id="OOI-cw-xBS"/>
11
+                <outlet property="hostTextField" destination="G3I-UT-srG" id="2UP-jx-iXY"/>
12
+                <outlet property="passwordTextField" destination="LED-xf-hz2" id="33t-eQ-j4s"/>
13
+                <outlet property="portTextField" destination="4ux-PB-rQU" id="GiJ-JU-7zH"/>
14
+                <outlet property="usernameTextField" destination="XCN-Nf-4ug" id="ZWL-TP-HMA"/>
15
+                <outlet property="view" destination="Hz6-mo-xeY" id="0bl-1N-x8E"/>
16
+            </connections>
17
+        </customObject>
18
+        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
19
+        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
20
+        <customView id="Hz6-mo-xeY">
21
+            <rect key="frame" x="0.0" y="0.0" width="382" height="227"/>
22
+            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
23
+            <subviews>
24
+                <stackView distribution="equalSpacing" orientation="vertical" alignment="centerX" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" translatesAutoresizingMaskIntoConstraints="NO" id="nVQ-9f-6mw">
25
+                    <rect key="frame" x="20" y="20" width="342" height="187"/>
26
+                    <subviews>
27
+                        <stackView distribution="fill" orientation="horizontal" alignment="centerY" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="UK9-tl-Z3M">
28
+                            <rect key="frame" x="61" y="166" width="220" height="21"/>
29
+                            <subviews>
30
+                                <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="m7P-8K-nqh">
31
+                                    <rect key="frame" x="-2" y="3" width="66" height="16"/>
32
+                                    <textFieldCell key="cell" lineBreakMode="clipping" alignment="right" title="Host" id="sog-MD-QDE">
33
+                                        <font key="font" usesAppearanceFont="YES"/>
34
+                                        <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
35
+                                        <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
36
+                                    </textFieldCell>
37
+                                </textField>
38
+                                <textField verticalHuggingPriority="750" textCompletion="NO" translatesAutoresizingMaskIntoConstraints="NO" id="G3I-UT-srG">
39
+                                    <rect key="frame" x="70" y="0.0" width="150" height="21"/>
40
+                                    <constraints>
41
+                                        <constraint firstAttribute="width" constant="150" id="aTL-rJ-8jf"/>
42
+                                    </constraints>
43
+                                    <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" borderStyle="bezel" title="localhost" drawsBackground="YES" id="gcm-8E-xTa">
44
+                                        <font key="font" metaFont="system"/>
45
+                                        <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
46
+                                        <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
47
+                                    </textFieldCell>
48
+                                    <connections>
49
+                                        <action selector="connect:" target="-2" id="aQG-Tp-D3w"/>
50
+                                    </connections>
51
+                                </textField>
52
+                            </subviews>
53
+                            <visibilityPriorities>
54
+                                <integer value="1000"/>
55
+                                <integer value="1000"/>
56
+                            </visibilityPriorities>
57
+                            <customSpacing>
58
+                                <real value="3.4028234663852886e+38"/>
59
+                                <real value="3.4028234663852886e+38"/>
60
+                            </customSpacing>
61
+                        </stackView>
62
+                        <stackView distribution="fill" orientation="horizontal" alignment="centerY" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="np6-tt-tmU">
63
+                            <rect key="frame" x="61" y="125" width="220" height="21"/>
64
+                            <subviews>
65
+                                <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Nlb-fr-bKz">
66
+                                    <rect key="frame" x="-2" y="2" width="66" height="16"/>
67
+                                    <textFieldCell key="cell" lineBreakMode="clipping" alignment="right" title="Port" id="OyW-Ac-JCc">
68
+                                        <font key="font" usesAppearanceFont="YES"/>
69
+                                        <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
70
+                                        <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
71
+                                    </textFieldCell>
72
+                                </textField>
73
+                                <textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="4ux-PB-rQU">
74
+                                    <rect key="frame" x="70" y="0.0" width="150" height="21"/>
75
+                                    <constraints>
76
+                                        <constraint firstAttribute="width" constant="150" id="Q0X-c7-gat"/>
77
+                                    </constraints>
78
+                                    <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" state="on" borderStyle="bezel" title="27017" drawsBackground="YES" id="TLc-N3-pMY">
79
+                                        <numberFormatter key="formatter" formatterBehavior="default10_4" usesGroupingSeparator="NO" formatWidth="-1" groupingSize="0" minimumIntegerDigits="1" maximumIntegerDigits="42" id="Pqq-af-3og"/>
80
+                                        <font key="font" metaFont="system"/>
81
+                                        <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
82
+                                        <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
83
+                                    </textFieldCell>
84
+                                    <connections>
85
+                                        <action selector="connect:" target="-2" id="bas-o8-xOJ"/>
86
+                                    </connections>
87
+                                </textField>
88
+                            </subviews>
89
+                            <visibilityPriorities>
90
+                                <integer value="1000"/>
91
+                                <integer value="1000"/>
92
+                            </visibilityPriorities>
93
+                            <customSpacing>
94
+                                <real value="3.4028234663852886e+38"/>
95
+                                <real value="3.4028234663852886e+38"/>
96
+                            </customSpacing>
97
+                        </stackView>
98
+                        <stackView distribution="fill" orientation="horizontal" alignment="centerY" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="jXy-MI-UpD">
99
+                            <rect key="frame" x="61" y="83" width="220" height="21"/>
100
+                            <subviews>
101
+                                <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Yai-sN-G1m">
102
+                                    <rect key="frame" x="-2" y="3" width="66" height="16"/>
103
+                                    <textFieldCell key="cell" lineBreakMode="clipping" alignment="right" title="Username" id="fXU-6C-WPE">
104
+                                        <font key="font" usesAppearanceFont="YES"/>
105
+                                        <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
106
+                                        <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
107
+                                    </textFieldCell>
108
+                                </textField>
109
+                                <textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="XCN-Nf-4ug">
110
+                                    <rect key="frame" x="70" y="0.0" width="150" height="21"/>
111
+                                    <constraints>
112
+                                        <constraint firstAttribute="width" constant="150" id="6rq-5E-pXI"/>
113
+                                    </constraints>
114
+                                    <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" borderStyle="bezel" placeholderString="No username" drawsBackground="YES" id="W6P-MV-flu">
115
+                                        <font key="font" metaFont="system"/>
116
+                                        <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
117
+                                        <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
118
+                                    </textFieldCell>
119
+                                    <connections>
120
+                                        <action selector="connect:" target="-2" id="KVE-gZ-6ij"/>
121
+                                    </connections>
122
+                                </textField>
123
+                            </subviews>
124
+                            <visibilityPriorities>
125
+                                <integer value="1000"/>
126
+                                <integer value="1000"/>
127
+                            </visibilityPriorities>
128
+                            <customSpacing>
129
+                                <real value="3.4028234663852886e+38"/>
130
+                                <real value="3.4028234663852886e+38"/>
131
+                            </customSpacing>
132
+                        </stackView>
133
+                        <stackView distribution="fill" orientation="horizontal" alignment="centerY" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="UGU-FU-PLg">
134
+                            <rect key="frame" x="61" y="42" width="220" height="21"/>
135
+                            <subviews>
136
+                                <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="IcB-Ib-a2d">
137
+                                    <rect key="frame" x="-2" y="2" width="66" height="16"/>
138
+                                    <textFieldCell key="cell" lineBreakMode="clipping" alignment="right" title="Password" id="Ov5-fg-Brc">
139
+                                        <font key="font" usesAppearanceFont="YES"/>
140
+                                        <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
141
+                                        <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
142
+                                    </textFieldCell>
143
+                                </textField>
144
+                                <secureTextField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="LED-xf-hz2">
145
+                                    <rect key="frame" x="70" y="0.0" width="150" height="21"/>
146
+                                    <constraints>
147
+                                        <constraint firstAttribute="width" constant="150" id="God-kM-PZb"/>
148
+                                    </constraints>
149
+                                    <secureTextFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" borderStyle="bezel" placeholderString="No password" drawsBackground="YES" usesSingleLineMode="YES" id="frH-9O-yiH">
150
+                                        <font key="font" metaFont="system"/>
151
+                                        <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
152
+                                        <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
153
+                                        <allowedInputSourceLocales>
154
+                                            <string>NSAllRomanInputSourcesLocaleIdentifier</string>
155
+                                        </allowedInputSourceLocales>
156
+                                    </secureTextFieldCell>
157
+                                    <connections>
158
+                                        <action selector="connect:" target="-2" id="p1U-Wv-7Fe"/>
159
+                                    </connections>
160
+                                </secureTextField>
161
+                            </subviews>
162
+                            <visibilityPriorities>
163
+                                <integer value="1000"/>
164
+                                <integer value="1000"/>
165
+                            </visibilityPriorities>
166
+                            <customSpacing>
167
+                                <real value="3.4028234663852886e+38"/>
168
+                                <real value="3.4028234663852886e+38"/>
169
+                            </customSpacing>
170
+                        </stackView>
171
+                        <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="uoF-7g-BAZ">
172
+                            <rect key="frame" x="125" y="-7" width="92" height="32"/>
173
+                            <buttonCell key="cell" type="push" title="Connect" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="zZ6-BB-6oE">
174
+                                <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
175
+                                <font key="font" metaFont="system"/>
176
+                            </buttonCell>
177
+                            <connections>
178
+                                <action selector="connect:" target="-2" id="cnG-a5-drV"/>
179
+                            </connections>
180
+                        </button>
181
+                    </subviews>
182
+                    <constraints>
183
+                        <constraint firstItem="XCN-Nf-4ug" firstAttribute="leading" secondItem="LED-xf-hz2" secondAttribute="leading" id="Nqy-TW-v1t"/>
184
+                        <constraint firstItem="4ux-PB-rQU" firstAttribute="leading" secondItem="G3I-UT-srG" secondAttribute="leading" id="SJh-Dt-zo1"/>
185
+                        <constraint firstItem="4ux-PB-rQU" firstAttribute="leading" secondItem="XCN-Nf-4ug" secondAttribute="leading" id="UwP-F3-GCN"/>
186
+                    </constraints>
187
+                    <visibilityPriorities>
188
+                        <integer value="1000"/>
189
+                        <integer value="1000"/>
190
+                        <integer value="1000"/>
191
+                        <integer value="1000"/>
192
+                        <integer value="1000"/>
193
+                    </visibilityPriorities>
194
+                    <customSpacing>
195
+                        <real value="3.4028234663852886e+38"/>
196
+                        <real value="3.4028234663852886e+38"/>
197
+                        <real value="3.4028234663852886e+38"/>
198
+                        <real value="3.4028234663852886e+38"/>
199
+                        <real value="3.4028234663852886e+38"/>
200
+                    </customSpacing>
201
+                </stackView>
202
+            </subviews>
203
+            <constraints>
204
+                <constraint firstAttribute="trailing" secondItem="nVQ-9f-6mw" secondAttribute="trailing" constant="20" symbolic="YES" id="4Fg-qK-q2q"/>
205
+                <constraint firstItem="nVQ-9f-6mw" firstAttribute="top" secondItem="Hz6-mo-xeY" secondAttribute="top" constant="20" symbolic="YES" id="L5h-ct-euM"/>
206
+                <constraint firstAttribute="bottom" secondItem="nVQ-9f-6mw" secondAttribute="bottom" constant="20" symbolic="YES" id="LWP-vb-E9k"/>
207
+                <constraint firstItem="nVQ-9f-6mw" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" constant="20" symbolic="YES" id="jfM-in-Oqg"/>
208
+            </constraints>
209
+            <point key="canvasLocation" x="91" y="131.5"/>
210
+        </customView>
211
+    </objects>
212
+</document>

+ 56
- 0
MongoView/Windows/DatabaseWindowController.swift View File

@@ -0,0 +1,56 @@
1
+//
2
+//  DatabaseWindowController.swift
3
+//  MongoView
4
+//
5
+//  Created by Shadowfacts on 1/9/20.
6
+//  Copyright © 2020 Shadowfacts. All rights reserved.
7
+//
8
+
9
+import Cocoa
10
+
11
+class DatabaseWindowController: NSWindowController {
12
+
13
+    private var titleObservation: NSKeyValueObservation?
14
+    
15
+    var mongoController: MongoController!
16
+    var initialCollection: DatabaseCollection?
17
+    
18
+    private var databaseViewController: DatabaseViewController!
19
+
20
+    convenience init() {
21
+        self.init(windowNibName: "DatabaseWindowController")
22
+    }
23
+    
24
+    override func windowDidLoad() {
25
+        super.windowDidLoad()
26
+
27
+        if mongoController == nil {
28
+            mongoController = MongoController(connectionString: "mongodb://localhost:27017")
29
+            mongoController.setup()
30
+        }
31
+
32
+        databaseViewController = DatabaseViewController(mongoController: mongoController)
33
+        contentViewController = databaseViewController
34
+        
35
+        if let initialCollection = initialCollection {
36
+            databaseViewController.showCollection(initialCollection)
37
+        }
38
+        
39
+        titleObservation = observe(\.contentViewController?.title) { [unowned self] (_, _) in
40
+            self.updateWindowTitle()
41
+        }
42
+        updateWindowTitle()
43
+        
44
+        window!.tabbingMode = .preferred
45
+        window!.tabbingIdentifier = mongoController.connectionString
46
+    }
47
+    
48
+    override func newWindowForTab(_ sender: Any?) {
49
+        (NSApplication.shared.delegate as! AppDelegate).newWindow(mongoController: mongoController)
50
+    }
51
+    
52
+    private func updateWindowTitle() {
53
+        window?.title = databaseViewController.title ?? "MongoView"
54
+    }
55
+
56
+}

+ 31
- 0
MongoView/Windows/DatabaseWindowController.xib View File

@@ -0,0 +1,31 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="15702" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
3
+    <dependencies>
4
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15702"/>
5
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
6
+    </dependencies>
7
+    <objects>
8
+        <customObject id="-2" userLabel="File's Owner" customClass="DatabaseWindowController" customModule="MongoView" customModuleProvider="target">
9
+            <connections>
10
+                <outlet property="window" destination="F0z-JX-Cv5" id="gIp-Ho-8D9"/>
11
+            </connections>
12
+        </customObject>
13
+        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
14
+        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
15
+        <window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="F0z-JX-Cv5">
16
+            <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
17
+            <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
18
+            <rect key="contentRect" x="196" y="240" width="480" height="270"/>
19
+            <rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
20
+            <view key="contentView" id="se5-gp-TjO">
21
+                <rect key="frame" x="0.0" y="0.0" width="480" height="270"/>
22
+                <autoresizingMask key="autoresizingMask"/>
23
+            </view>
24
+            <contentBorderThickness minY="22"/>
25
+            <connections>
26
+                <outlet property="delegate" destination="-2" id="0bl-1N-AYu"/>
27
+            </connections>
28
+            <point key="canvasLocation" x="141" y="147"/>
29
+        </window>
30
+    </objects>
31
+</document>

+ 27
- 0
MongoView/Windows/ServerConnectWindowController.swift View File

@@ -0,0 +1,27 @@
1
+//
2
+//  ServerConnectWindowController.swift
3
+//  MongoView
4
+//
5
+//  Created by Shadowfacts on 1/11/20.
6
+//  Copyright © 2020 Shadowfacts. All rights reserved.
7
+//
8
+
9
+import Cocoa
10
+
11
+class ServerConnectWindowController: NSWindowController {
12
+
13
+    weak var delegate: ServerConnectViewControllerDelegate?
14
+    
15
+    convenience init() {
16
+        self.init(windowNibName: "ServerConnectWindowController")
17
+    }
18
+    
19
+    override func windowDidLoad() {
20
+        super.windowDidLoad()
21
+
22
+        let vc = ServerConnectViewController()
23
+        vc.delegate = delegate
24
+        contentViewController = vc
25
+    }
26
+    
27
+}

+ 31
- 0
MongoView/Windows/ServerConnectWindowController.xib View File

@@ -0,0 +1,31 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="15702" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
3
+    <dependencies>
4
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15702"/>
5
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
6
+    </dependencies>
7
+    <objects>
8
+        <customObject id="-2" userLabel="File's Owner" customClass="ServerConnectWindowController" customModule="MongoView" customModuleProvider="target">
9
+            <connections>
10
+                <outlet property="window" destination="F0z-JX-Cv5" id="gIp-Ho-8D9"/>
11
+            </connections>
12
+        </customObject>
13
+        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
14
+        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
15
+        <window title="Connect to Server" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="alertPanel" tabbingMode="disallowed" id="F0z-JX-Cv5">
16
+            <windowStyleMask key="styleMask" titled="YES" closable="YES"/>
17
+            <windowCollectionBehavior key="collectionBehavior" fullScreenNone="YES"/>
18
+            <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
19
+            <rect key="contentRect" x="196" y="240" width="480" height="270"/>
20
+            <rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
21
+            <view key="contentView" id="se5-gp-TjO">
22
+                <rect key="frame" x="0.0" y="0.0" width="480" height="270"/>
23
+                <autoresizingMask key="autoresizingMask"/>
24
+            </view>
25
+            <connections>
26
+                <outlet property="delegate" destination="-2" id="0bl-1N-AYu"/>
27
+            </connections>
28
+            <point key="canvasLocation" x="141" y="147"/>
29
+        </window>
30
+    </objects>
31
+</document>

Loading…
Cancel
Save