├── .gitignore
├── .gitmodules
├── .travis.yml
├── README.md
├── swift-couchdb.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ ├── xcshareddata
│ │ ├── swift-couchdb.xccheckout
│ │ └── swift-couchdb.xcscmblueprint
│ └── xcuserdata
│ │ └── zemirco.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
├── xcshareddata
│ └── xcschemes
│ │ └── swift-couchdb.xcscheme
└── xcuserdata
│ └── zemirco.xcuserdatad
│ ├── xcdebugger
│ └── Breakpoints_v2.xcbkptlist
│ └── xcschemes
│ └── xcschememanagement.plist
├── swift-couchdb
├── AppDelegate.swift
├── Base.lproj
│ ├── LaunchScreen.xib
│ └── Main.storyboard
├── CouchDB.swift
├── Images.xcassets
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── Info.plist
├── MyDocument.swift
├── QueryString.swift
└── ViewController.swift
└── swift-couchdbTests
├── Info.plist
└── swift_couchdbTests.swift
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | .DS_Store
3 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "Alamofire"]
2 | path = Alamofire
3 | url = https://github.com/Alamofire/Alamofire.git
4 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 |
2 | services:
3 | - couchdb
4 |
5 | language: objective-c
6 |
7 | osx_image: xcode7.1
8 |
9 | xcode_project: swift-couchdb.xcodeproj
10 |
11 | xcode_scheme: swift-couchdb
12 |
13 | xcode_sdk: iphonesimulator
14 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # swift-couchdb
3 |
4 | [](https://travis-ci.org/zemirco/swift-couchdb)
5 |
6 | CouchDB client for Swift.
7 |
8 | ## Installation
9 |
10 | 1. Install [swift-http](https://github.com/zemirco/swift-http)
11 | 2. Copy `CouchDB.swift` from `./swift-couchdb/` into your project.
12 |
13 | ## Usage
14 |
15 | ```swift
16 |
17 | // create new client
18 | var couchdb = CouchDB(url: "http://localhost:5984", name: nil, password: nil)
19 |
20 | // use database
21 | var database = couchdb.use("mydb")
22 |
23 | // get document by id
24 | database.get("abc123") { response in
25 | switch response {
26 | case .Error(let error):
27 | println(error)
28 | case .Success(let data):
29 | println(data)
30 | }
31 | }
32 | ```
33 |
34 | ## Test
35 |
36 | cmd + u
37 |
38 | ## License
39 |
40 | MIT
41 |
--------------------------------------------------------------------------------
/swift-couchdb.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 3B046B181B9573480090B77C /* MyDocument.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B046B171B9573480090B77C /* MyDocument.swift */; };
11 | 3B068AFB1B34A21E00F27CBF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B068AFA1B34A21E00F27CBF /* AppDelegate.swift */; };
12 | 3B068AFD1B34A21E00F27CBF /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B068AFC1B34A21E00F27CBF /* ViewController.swift */; };
13 | 3B068B001B34A21E00F27CBF /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3B068AFE1B34A21E00F27CBF /* Main.storyboard */; };
14 | 3B068B021B34A21E00F27CBF /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3B068B011B34A21E00F27CBF /* Images.xcassets */; };
15 | 3B068B051B34A21E00F27CBF /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3B068B031B34A21E00F27CBF /* LaunchScreen.xib */; };
16 | 3B068B111B34A21E00F27CBF /* swift_couchdbTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B068B101B34A21E00F27CBF /* swift_couchdbTests.swift */; };
17 | 3B4BF0091DB1F60500F3CBD0 /* QueryString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B4BF0081DB1F60500F3CBD0 /* QueryString.swift */; };
18 | 3BE25E321B9C8A70008705F6 /* CouchDB.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BE25E311B9C8A70008705F6 /* CouchDB.swift */; };
19 | /* End PBXBuildFile section */
20 |
21 | /* Begin PBXContainerItemProxy section */
22 | 3B068B0B1B34A21E00F27CBF /* PBXContainerItemProxy */ = {
23 | isa = PBXContainerItemProxy;
24 | containerPortal = 3B068AED1B34A21E00F27CBF /* Project object */;
25 | proxyType = 1;
26 | remoteGlobalIDString = 3B068AF41B34A21E00F27CBF;
27 | remoteInfo = "swift-couchdb";
28 | };
29 | 3B1B09261E47B3380060A062 /* PBXContainerItemProxy */ = {
30 | isa = PBXContainerItemProxy;
31 | containerPortal = 3B1B091B1E47B3380060A062 /* Alamofire.xcodeproj */;
32 | proxyType = 2;
33 | remoteGlobalIDString = F8111E3319A95C8B0040E7D1;
34 | remoteInfo = "Alamofire iOS";
35 | };
36 | 3B1B09281E47B3380060A062 /* PBXContainerItemProxy */ = {
37 | isa = PBXContainerItemProxy;
38 | containerPortal = 3B1B091B1E47B3380060A062 /* Alamofire.xcodeproj */;
39 | proxyType = 2;
40 | remoteGlobalIDString = F8111E3E19A95C8B0040E7D1;
41 | remoteInfo = "Alamofire iOS Tests";
42 | };
43 | 3B1B092A1E47B3380060A062 /* PBXContainerItemProxy */ = {
44 | isa = PBXContainerItemProxy;
45 | containerPortal = 3B1B091B1E47B3380060A062 /* Alamofire.xcodeproj */;
46 | proxyType = 2;
47 | remoteGlobalIDString = 4DD67C0B1A5C55C900ED2280;
48 | remoteInfo = "Alamofire macOS";
49 | };
50 | 3B1B092C1E47B3380060A062 /* PBXContainerItemProxy */ = {
51 | isa = PBXContainerItemProxy;
52 | containerPortal = 3B1B091B1E47B3380060A062 /* Alamofire.xcodeproj */;
53 | proxyType = 2;
54 | remoteGlobalIDString = F829C6B21A7A94F100A2CD59;
55 | remoteInfo = "Alamofire macOS Tests";
56 | };
57 | 3B1B092E1E47B3380060A062 /* PBXContainerItemProxy */ = {
58 | isa = PBXContainerItemProxy;
59 | containerPortal = 3B1B091B1E47B3380060A062 /* Alamofire.xcodeproj */;
60 | proxyType = 2;
61 | remoteGlobalIDString = 4CF626EF1BA7CB3E0011A099;
62 | remoteInfo = "Alamofire tvOS";
63 | };
64 | 3B1B09301E47B3380060A062 /* PBXContainerItemProxy */ = {
65 | isa = PBXContainerItemProxy;
66 | containerPortal = 3B1B091B1E47B3380060A062 /* Alamofire.xcodeproj */;
67 | proxyType = 2;
68 | remoteGlobalIDString = 4CF626F81BA7CB3E0011A099;
69 | remoteInfo = "Alamofire tvOS Tests";
70 | };
71 | 3B1B09321E47B3380060A062 /* PBXContainerItemProxy */ = {
72 | isa = PBXContainerItemProxy;
73 | containerPortal = 3B1B091B1E47B3380060A062 /* Alamofire.xcodeproj */;
74 | proxyType = 2;
75 | remoteGlobalIDString = E4202FE01B667AA100C997FB;
76 | remoteInfo = "Alamofire watchOS";
77 | };
78 | /* End PBXContainerItemProxy section */
79 |
80 | /* Begin PBXFileReference section */
81 | 3B046B171B9573480090B77C /* MyDocument.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MyDocument.swift; sourceTree = ""; };
82 | 3B068AF51B34A21E00F27CBF /* swift-couchdb.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "swift-couchdb.app"; sourceTree = BUILT_PRODUCTS_DIR; };
83 | 3B068AF91B34A21E00F27CBF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
84 | 3B068AFA1B34A21E00F27CBF /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
85 | 3B068AFC1B34A21E00F27CBF /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
86 | 3B068AFF1B34A21E00F27CBF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
87 | 3B068B011B34A21E00F27CBF /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
88 | 3B068B041B34A21E00F27CBF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; };
89 | 3B068B0A1B34A21E00F27CBF /* swift-couchdbTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "swift-couchdbTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
90 | 3B068B0F1B34A21E00F27CBF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
91 | 3B068B101B34A21E00F27CBF /* swift_couchdbTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = swift_couchdbTests.swift; sourceTree = ""; };
92 | 3B1B091B1E47B3380060A062 /* Alamofire.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Alamofire.xcodeproj; path = Alamofire/Alamofire.xcodeproj; sourceTree = ""; };
93 | 3B4BF0081DB1F60500F3CBD0 /* QueryString.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueryString.swift; sourceTree = ""; };
94 | 3BE25E311B9C8A70008705F6 /* CouchDB.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CouchDB.swift; sourceTree = ""; };
95 | /* End PBXFileReference section */
96 |
97 | /* Begin PBXFrameworksBuildPhase section */
98 | 3B068AF21B34A21E00F27CBF /* Frameworks */ = {
99 | isa = PBXFrameworksBuildPhase;
100 | buildActionMask = 2147483647;
101 | files = (
102 | );
103 | runOnlyForDeploymentPostprocessing = 0;
104 | };
105 | 3B068B071B34A21E00F27CBF /* Frameworks */ = {
106 | isa = PBXFrameworksBuildPhase;
107 | buildActionMask = 2147483647;
108 | files = (
109 | );
110 | runOnlyForDeploymentPostprocessing = 0;
111 | };
112 | /* End PBXFrameworksBuildPhase section */
113 |
114 | /* Begin PBXGroup section */
115 | 3B068AEC1B34A21E00F27CBF = {
116 | isa = PBXGroup;
117 | children = (
118 | 3B1B091B1E47B3380060A062 /* Alamofire.xcodeproj */,
119 | 3B068AF71B34A21E00F27CBF /* swift-couchdb */,
120 | 3B068B0D1B34A21E00F27CBF /* swift-couchdbTests */,
121 | 3B068AF61B34A21E00F27CBF /* Products */,
122 | );
123 | sourceTree = "";
124 | };
125 | 3B068AF61B34A21E00F27CBF /* Products */ = {
126 | isa = PBXGroup;
127 | children = (
128 | 3B068AF51B34A21E00F27CBF /* swift-couchdb.app */,
129 | 3B068B0A1B34A21E00F27CBF /* swift-couchdbTests.xctest */,
130 | );
131 | name = Products;
132 | sourceTree = "";
133 | };
134 | 3B068AF71B34A21E00F27CBF /* swift-couchdb */ = {
135 | isa = PBXGroup;
136 | children = (
137 | 3B068AFA1B34A21E00F27CBF /* AppDelegate.swift */,
138 | 3B068AFC1B34A21E00F27CBF /* ViewController.swift */,
139 | 3B046B171B9573480090B77C /* MyDocument.swift */,
140 | 3BE25E311B9C8A70008705F6 /* CouchDB.swift */,
141 | 3B4BF0081DB1F60500F3CBD0 /* QueryString.swift */,
142 | 3B068AFE1B34A21E00F27CBF /* Main.storyboard */,
143 | 3B068B011B34A21E00F27CBF /* Images.xcassets */,
144 | 3B068B031B34A21E00F27CBF /* LaunchScreen.xib */,
145 | 3B068AF81B34A21E00F27CBF /* Supporting Files */,
146 | );
147 | path = "swift-couchdb";
148 | sourceTree = "";
149 | };
150 | 3B068AF81B34A21E00F27CBF /* Supporting Files */ = {
151 | isa = PBXGroup;
152 | children = (
153 | 3B068AF91B34A21E00F27CBF /* Info.plist */,
154 | );
155 | name = "Supporting Files";
156 | sourceTree = "";
157 | };
158 | 3B068B0D1B34A21E00F27CBF /* swift-couchdbTests */ = {
159 | isa = PBXGroup;
160 | children = (
161 | 3B068B101B34A21E00F27CBF /* swift_couchdbTests.swift */,
162 | 3B068B0E1B34A21E00F27CBF /* Supporting Files */,
163 | );
164 | path = "swift-couchdbTests";
165 | sourceTree = "";
166 | };
167 | 3B068B0E1B34A21E00F27CBF /* Supporting Files */ = {
168 | isa = PBXGroup;
169 | children = (
170 | 3B068B0F1B34A21E00F27CBF /* Info.plist */,
171 | );
172 | name = "Supporting Files";
173 | sourceTree = "";
174 | };
175 | 3B1B091C1E47B3380060A062 /* Products */ = {
176 | isa = PBXGroup;
177 | children = (
178 | 3B1B09271E47B3380060A062 /* Alamofire.framework */,
179 | 3B1B09291E47B3380060A062 /* Alamofire iOS Tests.xctest */,
180 | 3B1B092B1E47B3380060A062 /* Alamofire.framework */,
181 | 3B1B092D1E47B3380060A062 /* Alamofire macOS Tests.xctest */,
182 | 3B1B092F1E47B3380060A062 /* Alamofire.framework */,
183 | 3B1B09311E47B3380060A062 /* Alamofire tvOS Tests.xctest */,
184 | 3B1B09331E47B3380060A062 /* Alamofire.framework */,
185 | );
186 | name = Products;
187 | sourceTree = "";
188 | };
189 | /* End PBXGroup section */
190 |
191 | /* Begin PBXNativeTarget section */
192 | 3B068AF41B34A21E00F27CBF /* swift-couchdb */ = {
193 | isa = PBXNativeTarget;
194 | buildConfigurationList = 3B068B141B34A21E00F27CBF /* Build configuration list for PBXNativeTarget "swift-couchdb" */;
195 | buildPhases = (
196 | 3B068AF11B34A21E00F27CBF /* Sources */,
197 | 3B068AF21B34A21E00F27CBF /* Frameworks */,
198 | 3B068AF31B34A21E00F27CBF /* Resources */,
199 | );
200 | buildRules = (
201 | );
202 | dependencies = (
203 | );
204 | name = "swift-couchdb";
205 | productName = "swift-couchdb";
206 | productReference = 3B068AF51B34A21E00F27CBF /* swift-couchdb.app */;
207 | productType = "com.apple.product-type.application";
208 | };
209 | 3B068B091B34A21E00F27CBF /* swift-couchdbTests */ = {
210 | isa = PBXNativeTarget;
211 | buildConfigurationList = 3B068B171B34A21E00F27CBF /* Build configuration list for PBXNativeTarget "swift-couchdbTests" */;
212 | buildPhases = (
213 | 3B068B061B34A21E00F27CBF /* Sources */,
214 | 3B068B071B34A21E00F27CBF /* Frameworks */,
215 | 3B068B081B34A21E00F27CBF /* Resources */,
216 | );
217 | buildRules = (
218 | );
219 | dependencies = (
220 | 3B068B0C1B34A21E00F27CBF /* PBXTargetDependency */,
221 | );
222 | name = "swift-couchdbTests";
223 | productName = "swift-couchdbTests";
224 | productReference = 3B068B0A1B34A21E00F27CBF /* swift-couchdbTests.xctest */;
225 | productType = "com.apple.product-type.bundle.unit-test";
226 | };
227 | /* End PBXNativeTarget section */
228 |
229 | /* Begin PBXProject section */
230 | 3B068AED1B34A21E00F27CBF /* Project object */ = {
231 | isa = PBXProject;
232 | attributes = {
233 | LastSwiftMigration = 0700;
234 | LastSwiftUpdateCheck = 0700;
235 | LastUpgradeCheck = 0820;
236 | ORGANIZATIONNAME = zemirco;
237 | TargetAttributes = {
238 | 3B068AF41B34A21E00F27CBF = {
239 | CreatedOnToolsVersion = 6.3.2;
240 | LastSwiftMigration = 0800;
241 | };
242 | 3B068B091B34A21E00F27CBF = {
243 | CreatedOnToolsVersion = 6.3.2;
244 | LastSwiftMigration = 0800;
245 | TestTargetID = 3B068AF41B34A21E00F27CBF;
246 | };
247 | };
248 | };
249 | buildConfigurationList = 3B068AF01B34A21E00F27CBF /* Build configuration list for PBXProject "swift-couchdb" */;
250 | compatibilityVersion = "Xcode 3.2";
251 | developmentRegion = English;
252 | hasScannedForEncodings = 0;
253 | knownRegions = (
254 | en,
255 | Base,
256 | );
257 | mainGroup = 3B068AEC1B34A21E00F27CBF;
258 | productRefGroup = 3B068AF61B34A21E00F27CBF /* Products */;
259 | projectDirPath = "";
260 | projectReferences = (
261 | {
262 | ProductGroup = 3B1B091C1E47B3380060A062 /* Products */;
263 | ProjectRef = 3B1B091B1E47B3380060A062 /* Alamofire.xcodeproj */;
264 | },
265 | );
266 | projectRoot = "";
267 | targets = (
268 | 3B068AF41B34A21E00F27CBF /* swift-couchdb */,
269 | 3B068B091B34A21E00F27CBF /* swift-couchdbTests */,
270 | );
271 | };
272 | /* End PBXProject section */
273 |
274 | /* Begin PBXReferenceProxy section */
275 | 3B1B09271E47B3380060A062 /* Alamofire.framework */ = {
276 | isa = PBXReferenceProxy;
277 | fileType = wrapper.framework;
278 | path = Alamofire.framework;
279 | remoteRef = 3B1B09261E47B3380060A062 /* PBXContainerItemProxy */;
280 | sourceTree = BUILT_PRODUCTS_DIR;
281 | };
282 | 3B1B09291E47B3380060A062 /* Alamofire iOS Tests.xctest */ = {
283 | isa = PBXReferenceProxy;
284 | fileType = wrapper.cfbundle;
285 | path = "Alamofire iOS Tests.xctest";
286 | remoteRef = 3B1B09281E47B3380060A062 /* PBXContainerItemProxy */;
287 | sourceTree = BUILT_PRODUCTS_DIR;
288 | };
289 | 3B1B092B1E47B3380060A062 /* Alamofire.framework */ = {
290 | isa = PBXReferenceProxy;
291 | fileType = wrapper.framework;
292 | path = Alamofire.framework;
293 | remoteRef = 3B1B092A1E47B3380060A062 /* PBXContainerItemProxy */;
294 | sourceTree = BUILT_PRODUCTS_DIR;
295 | };
296 | 3B1B092D1E47B3380060A062 /* Alamofire macOS Tests.xctest */ = {
297 | isa = PBXReferenceProxy;
298 | fileType = wrapper.cfbundle;
299 | path = "Alamofire macOS Tests.xctest";
300 | remoteRef = 3B1B092C1E47B3380060A062 /* PBXContainerItemProxy */;
301 | sourceTree = BUILT_PRODUCTS_DIR;
302 | };
303 | 3B1B092F1E47B3380060A062 /* Alamofire.framework */ = {
304 | isa = PBXReferenceProxy;
305 | fileType = wrapper.framework;
306 | path = Alamofire.framework;
307 | remoteRef = 3B1B092E1E47B3380060A062 /* PBXContainerItemProxy */;
308 | sourceTree = BUILT_PRODUCTS_DIR;
309 | };
310 | 3B1B09311E47B3380060A062 /* Alamofire tvOS Tests.xctest */ = {
311 | isa = PBXReferenceProxy;
312 | fileType = wrapper.cfbundle;
313 | path = "Alamofire tvOS Tests.xctest";
314 | remoteRef = 3B1B09301E47B3380060A062 /* PBXContainerItemProxy */;
315 | sourceTree = BUILT_PRODUCTS_DIR;
316 | };
317 | 3B1B09331E47B3380060A062 /* Alamofire.framework */ = {
318 | isa = PBXReferenceProxy;
319 | fileType = wrapper.framework;
320 | path = Alamofire.framework;
321 | remoteRef = 3B1B09321E47B3380060A062 /* PBXContainerItemProxy */;
322 | sourceTree = BUILT_PRODUCTS_DIR;
323 | };
324 | /* End PBXReferenceProxy section */
325 |
326 | /* Begin PBXResourcesBuildPhase section */
327 | 3B068AF31B34A21E00F27CBF /* Resources */ = {
328 | isa = PBXResourcesBuildPhase;
329 | buildActionMask = 2147483647;
330 | files = (
331 | 3B068B001B34A21E00F27CBF /* Main.storyboard in Resources */,
332 | 3B068B051B34A21E00F27CBF /* LaunchScreen.xib in Resources */,
333 | 3B068B021B34A21E00F27CBF /* Images.xcassets in Resources */,
334 | );
335 | runOnlyForDeploymentPostprocessing = 0;
336 | };
337 | 3B068B081B34A21E00F27CBF /* Resources */ = {
338 | isa = PBXResourcesBuildPhase;
339 | buildActionMask = 2147483647;
340 | files = (
341 | );
342 | runOnlyForDeploymentPostprocessing = 0;
343 | };
344 | /* End PBXResourcesBuildPhase section */
345 |
346 | /* Begin PBXSourcesBuildPhase section */
347 | 3B068AF11B34A21E00F27CBF /* Sources */ = {
348 | isa = PBXSourcesBuildPhase;
349 | buildActionMask = 2147483647;
350 | files = (
351 | 3B068AFD1B34A21E00F27CBF /* ViewController.swift in Sources */,
352 | 3B4BF0091DB1F60500F3CBD0 /* QueryString.swift in Sources */,
353 | 3BE25E321B9C8A70008705F6 /* CouchDB.swift in Sources */,
354 | 3B046B181B9573480090B77C /* MyDocument.swift in Sources */,
355 | 3B068AFB1B34A21E00F27CBF /* AppDelegate.swift in Sources */,
356 | );
357 | runOnlyForDeploymentPostprocessing = 0;
358 | };
359 | 3B068B061B34A21E00F27CBF /* Sources */ = {
360 | isa = PBXSourcesBuildPhase;
361 | buildActionMask = 2147483647;
362 | files = (
363 | 3B068B111B34A21E00F27CBF /* swift_couchdbTests.swift in Sources */,
364 | );
365 | runOnlyForDeploymentPostprocessing = 0;
366 | };
367 | /* End PBXSourcesBuildPhase section */
368 |
369 | /* Begin PBXTargetDependency section */
370 | 3B068B0C1B34A21E00F27CBF /* PBXTargetDependency */ = {
371 | isa = PBXTargetDependency;
372 | target = 3B068AF41B34A21E00F27CBF /* swift-couchdb */;
373 | targetProxy = 3B068B0B1B34A21E00F27CBF /* PBXContainerItemProxy */;
374 | };
375 | /* End PBXTargetDependency section */
376 |
377 | /* Begin PBXVariantGroup section */
378 | 3B068AFE1B34A21E00F27CBF /* Main.storyboard */ = {
379 | isa = PBXVariantGroup;
380 | children = (
381 | 3B068AFF1B34A21E00F27CBF /* Base */,
382 | );
383 | name = Main.storyboard;
384 | sourceTree = "";
385 | };
386 | 3B068B031B34A21E00F27CBF /* LaunchScreen.xib */ = {
387 | isa = PBXVariantGroup;
388 | children = (
389 | 3B068B041B34A21E00F27CBF /* Base */,
390 | );
391 | name = LaunchScreen.xib;
392 | sourceTree = "";
393 | };
394 | /* End PBXVariantGroup section */
395 |
396 | /* Begin XCBuildConfiguration section */
397 | 3B068B121B34A21E00F27CBF /* Debug */ = {
398 | isa = XCBuildConfiguration;
399 | buildSettings = {
400 | ALWAYS_SEARCH_USER_PATHS = NO;
401 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
402 | CLANG_CXX_LIBRARY = "libc++";
403 | CLANG_ENABLE_MODULES = YES;
404 | CLANG_ENABLE_OBJC_ARC = YES;
405 | CLANG_WARN_BOOL_CONVERSION = YES;
406 | CLANG_WARN_CONSTANT_CONVERSION = YES;
407 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
408 | CLANG_WARN_EMPTY_BODY = YES;
409 | CLANG_WARN_ENUM_CONVERSION = YES;
410 | CLANG_WARN_INFINITE_RECURSION = YES;
411 | CLANG_WARN_INT_CONVERSION = YES;
412 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
413 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
414 | CLANG_WARN_UNREACHABLE_CODE = YES;
415 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
416 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
417 | COPY_PHASE_STRIP = NO;
418 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
419 | ENABLE_STRICT_OBJC_MSGSEND = YES;
420 | ENABLE_TESTABILITY = YES;
421 | GCC_C_LANGUAGE_STANDARD = gnu99;
422 | GCC_DYNAMIC_NO_PIC = NO;
423 | GCC_NO_COMMON_BLOCKS = YES;
424 | GCC_OPTIMIZATION_LEVEL = 0;
425 | GCC_PREPROCESSOR_DEFINITIONS = (
426 | "DEBUG=1",
427 | "$(inherited)",
428 | );
429 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
430 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
431 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
432 | GCC_WARN_UNDECLARED_SELECTOR = YES;
433 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
434 | GCC_WARN_UNUSED_FUNCTION = YES;
435 | GCC_WARN_UNUSED_VARIABLE = YES;
436 | IPHONEOS_DEPLOYMENT_TARGET = 8.3;
437 | MTL_ENABLE_DEBUG_INFO = YES;
438 | ONLY_ACTIVE_ARCH = YES;
439 | SDKROOT = iphoneos;
440 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
441 | TARGETED_DEVICE_FAMILY = "1,2";
442 | };
443 | name = Debug;
444 | };
445 | 3B068B131B34A21E00F27CBF /* Release */ = {
446 | isa = XCBuildConfiguration;
447 | buildSettings = {
448 | ALWAYS_SEARCH_USER_PATHS = NO;
449 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
450 | CLANG_CXX_LIBRARY = "libc++";
451 | CLANG_ENABLE_MODULES = YES;
452 | CLANG_ENABLE_OBJC_ARC = YES;
453 | CLANG_WARN_BOOL_CONVERSION = YES;
454 | CLANG_WARN_CONSTANT_CONVERSION = YES;
455 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
456 | CLANG_WARN_EMPTY_BODY = YES;
457 | CLANG_WARN_ENUM_CONVERSION = YES;
458 | CLANG_WARN_INFINITE_RECURSION = YES;
459 | CLANG_WARN_INT_CONVERSION = YES;
460 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
461 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
462 | CLANG_WARN_UNREACHABLE_CODE = YES;
463 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
464 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
465 | COPY_PHASE_STRIP = NO;
466 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
467 | ENABLE_NS_ASSERTIONS = NO;
468 | ENABLE_STRICT_OBJC_MSGSEND = YES;
469 | GCC_C_LANGUAGE_STANDARD = gnu99;
470 | GCC_NO_COMMON_BLOCKS = YES;
471 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
472 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
473 | GCC_WARN_UNDECLARED_SELECTOR = YES;
474 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
475 | GCC_WARN_UNUSED_FUNCTION = YES;
476 | GCC_WARN_UNUSED_VARIABLE = YES;
477 | IPHONEOS_DEPLOYMENT_TARGET = 8.3;
478 | MTL_ENABLE_DEBUG_INFO = NO;
479 | SDKROOT = iphoneos;
480 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
481 | TARGETED_DEVICE_FAMILY = "1,2";
482 | VALIDATE_PRODUCT = YES;
483 | };
484 | name = Release;
485 | };
486 | 3B068B151B34A21E00F27CBF /* Debug */ = {
487 | isa = XCBuildConfiguration;
488 | buildSettings = {
489 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
490 | INFOPLIST_FILE = "swift-couchdb/Info.plist";
491 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
492 | PRODUCT_BUNDLE_IDENTIFIER = "zemirco.$(PRODUCT_NAME:rfc1034identifier)";
493 | PRODUCT_NAME = "$(TARGET_NAME)";
494 | SWIFT_VERSION = 3.0;
495 | };
496 | name = Debug;
497 | };
498 | 3B068B161B34A21E00F27CBF /* Release */ = {
499 | isa = XCBuildConfiguration;
500 | buildSettings = {
501 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
502 | INFOPLIST_FILE = "swift-couchdb/Info.plist";
503 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
504 | PRODUCT_BUNDLE_IDENTIFIER = "zemirco.$(PRODUCT_NAME:rfc1034identifier)";
505 | PRODUCT_NAME = "$(TARGET_NAME)";
506 | SWIFT_VERSION = 3.0;
507 | };
508 | name = Release;
509 | };
510 | 3B068B181B34A21E00F27CBF /* Debug */ = {
511 | isa = XCBuildConfiguration;
512 | buildSettings = {
513 | BUNDLE_LOADER = "$(TEST_HOST)";
514 | FRAMEWORK_SEARCH_PATHS = (
515 | "$(SDKROOT)/Developer/Library/Frameworks",
516 | "$(inherited)",
517 | );
518 | GCC_PREPROCESSOR_DEFINITIONS = (
519 | "DEBUG=1",
520 | "$(inherited)",
521 | );
522 | INFOPLIST_FILE = "swift-couchdbTests/Info.plist";
523 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
524 | PRODUCT_BUNDLE_IDENTIFIER = "zemirco.$(PRODUCT_NAME:rfc1034identifier)";
525 | PRODUCT_NAME = "$(TARGET_NAME)";
526 | SWIFT_VERSION = 3.0;
527 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/swift-couchdb.app/swift-couchdb";
528 | };
529 | name = Debug;
530 | };
531 | 3B068B191B34A21E00F27CBF /* Release */ = {
532 | isa = XCBuildConfiguration;
533 | buildSettings = {
534 | BUNDLE_LOADER = "$(TEST_HOST)";
535 | FRAMEWORK_SEARCH_PATHS = (
536 | "$(SDKROOT)/Developer/Library/Frameworks",
537 | "$(inherited)",
538 | );
539 | INFOPLIST_FILE = "swift-couchdbTests/Info.plist";
540 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
541 | PRODUCT_BUNDLE_IDENTIFIER = "zemirco.$(PRODUCT_NAME:rfc1034identifier)";
542 | PRODUCT_NAME = "$(TARGET_NAME)";
543 | SWIFT_VERSION = 3.0;
544 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/swift-couchdb.app/swift-couchdb";
545 | };
546 | name = Release;
547 | };
548 | /* End XCBuildConfiguration section */
549 |
550 | /* Begin XCConfigurationList section */
551 | 3B068AF01B34A21E00F27CBF /* Build configuration list for PBXProject "swift-couchdb" */ = {
552 | isa = XCConfigurationList;
553 | buildConfigurations = (
554 | 3B068B121B34A21E00F27CBF /* Debug */,
555 | 3B068B131B34A21E00F27CBF /* Release */,
556 | );
557 | defaultConfigurationIsVisible = 0;
558 | defaultConfigurationName = Release;
559 | };
560 | 3B068B141B34A21E00F27CBF /* Build configuration list for PBXNativeTarget "swift-couchdb" */ = {
561 | isa = XCConfigurationList;
562 | buildConfigurations = (
563 | 3B068B151B34A21E00F27CBF /* Debug */,
564 | 3B068B161B34A21E00F27CBF /* Release */,
565 | );
566 | defaultConfigurationIsVisible = 0;
567 | defaultConfigurationName = Release;
568 | };
569 | 3B068B171B34A21E00F27CBF /* Build configuration list for PBXNativeTarget "swift-couchdbTests" */ = {
570 | isa = XCConfigurationList;
571 | buildConfigurations = (
572 | 3B068B181B34A21E00F27CBF /* Debug */,
573 | 3B068B191B34A21E00F27CBF /* Release */,
574 | );
575 | defaultConfigurationIsVisible = 0;
576 | defaultConfigurationName = Release;
577 | };
578 | /* End XCConfigurationList section */
579 | };
580 | rootObject = 3B068AED1B34A21E00F27CBF /* Project object */;
581 | }
582 |
--------------------------------------------------------------------------------
/swift-couchdb.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/swift-couchdb.xcodeproj/project.xcworkspace/xcshareddata/swift-couchdb.xccheckout:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDESourceControlProjectFavoriteDictionaryKey
6 |
7 | IDESourceControlProjectIdentifier
8 | 2F799FC9-C0AB-4634-B472-46C8ACED133F
9 | IDESourceControlProjectName
10 | swift-couchdb
11 | IDESourceControlProjectOriginsDictionary
12 |
13 | 02F4FDB20D0E78E4168FDE7131FBED42485EBD9E
14 | github.com:zemirco/swift-couchdb.git
15 |
16 | IDESourceControlProjectPath
17 | swift-couchdb.xcodeproj
18 | IDESourceControlProjectRelativeInstallPathDictionary
19 |
20 | 02F4FDB20D0E78E4168FDE7131FBED42485EBD9E
21 | ../..
22 |
23 | IDESourceControlProjectURL
24 | github.com:zemirco/swift-couchdb.git
25 | IDESourceControlProjectVersion
26 | 111
27 | IDESourceControlProjectWCCIdentifier
28 | 02F4FDB20D0E78E4168FDE7131FBED42485EBD9E
29 | IDESourceControlProjectWCConfigurations
30 |
31 |
32 | IDESourceControlRepositoryExtensionIdentifierKey
33 | public.vcs.git
34 | IDESourceControlWCCIdentifierKey
35 | 02F4FDB20D0E78E4168FDE7131FBED42485EBD9E
36 | IDESourceControlWCCName
37 | swift-couchdb
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/swift-couchdb.xcodeproj/project.xcworkspace/xcshareddata/swift-couchdb.xcscmblueprint:
--------------------------------------------------------------------------------
1 | {
2 | "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "02F4FDB20D0E78E4168FDE7131FBED42485EBD9E",
3 | "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : {
4 |
5 | },
6 | "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : {
7 | "02F4FDB20D0E78E4168FDE7131FBED42485EBD9E" : 0,
8 | "67620B5EFA902936DF04070AF595B76AB0333747" : 9223372036854775807
9 | },
10 | "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "2F799FC9-C0AB-4634-B472-46C8ACED133F",
11 | "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : {
12 | "02F4FDB20D0E78E4168FDE7131FBED42485EBD9E" : "swift-couchdb\/",
13 | "67620B5EFA902936DF04070AF595B76AB0333747" : "swift-couchdb\/Alamofire\/"
14 | },
15 | "DVTSourceControlWorkspaceBlueprintNameKey" : "swift-couchdb",
16 | "DVTSourceControlWorkspaceBlueprintVersion" : 204,
17 | "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "swift-couchdb.xcodeproj",
18 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [
19 | {
20 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "github.com:zemirco\/swift-couchdb.git",
21 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
22 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "02F4FDB20D0E78E4168FDE7131FBED42485EBD9E"
23 | },
24 | {
25 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/Alamofire\/Alamofire.git",
26 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
27 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "67620B5EFA902936DF04070AF595B76AB0333747"
28 | }
29 | ]
30 | }
--------------------------------------------------------------------------------
/swift-couchdb.xcodeproj/project.xcworkspace/xcuserdata/zemirco.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zemirco/swift-couchdb/60aca27435b18fb1a0132edb9f106d0630c63801/swift-couchdb.xcodeproj/project.xcworkspace/xcuserdata/zemirco.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/swift-couchdb.xcodeproj/xcshareddata/xcschemes/swift-couchdb.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
29 |
35 |
36 |
37 |
38 |
39 |
44 |
45 |
47 |
53 |
54 |
55 |
56 |
57 |
63 |
64 |
65 |
66 |
67 |
68 |
78 |
80 |
86 |
87 |
88 |
89 |
90 |
91 |
97 |
99 |
105 |
106 |
107 |
108 |
110 |
111 |
114 |
115 |
116 |
--------------------------------------------------------------------------------
/swift-couchdb.xcodeproj/xcuserdata/zemirco.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/swift-couchdb.xcodeproj/xcuserdata/zemirco.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | swift-couchdb.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | 3B068AF41B34A21E00F27CBF
16 |
17 | primary
18 |
19 |
20 | 3B068B091B34A21E00F27CBF
21 |
22 | primary
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/swift-couchdb/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // swift-couchdb
4 | //
5 | // Created by Mirco Zeiss on 6/19/15.
6 | // Copyright (c) 2015 zemirco. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow?
15 |
16 |
17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
18 | // Override point for customization after application launch.
19 | return true
20 | }
21 |
22 | func applicationWillResignActive(_ application: UIApplication) {
23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
24 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
25 | }
26 |
27 | func applicationDidEnterBackground(_ application: UIApplication) {
28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
30 | }
31 |
32 | func applicationWillEnterForeground(_ application: UIApplication) {
33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
34 | }
35 |
36 | func applicationDidBecomeActive(_ application: UIApplication) {
37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
38 | }
39 |
40 | func applicationWillTerminate(_ application: UIApplication) {
41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
42 | }
43 |
44 |
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/swift-couchdb/Base.lproj/LaunchScreen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
20 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/swift-couchdb/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/swift-couchdb/CouchDB.swift:
--------------------------------------------------------------------------------
1 |
2 | import Alamofire
3 |
4 | open class CouchDB {
5 |
6 | fileprivate var url: String
7 | fileprivate var headers: [String: String]?
8 |
9 | public init(url: String, name: String?, password: String?) {
10 | self.url = url.hasSuffix("/") ? url : "\(url)/"
11 | if let name = name, let password = password {
12 | let auth = "\(name):\(password)"
13 | let data = auth.data(using: String.Encoding.utf8)
14 | let base = data!.base64EncodedString(options: [])
15 | self.headers = [
16 | "Authorization": "Basic \(base)"
17 | ]
18 | }
19 | }
20 |
21 | public init(url: String, cookie: HTTPCookie) {
22 | self.url = url.hasSuffix("/") ? url : "\(url)/"
23 | Alamofire.SessionManager.default.session.configuration.httpCookieStorage?.setCookie(cookie)
24 | }
25 |
26 | /**
27 | * Info
28 | *
29 | * http://docs.couchdb.org/en/1.6.1/api/server/common.html#get--
30 | */
31 | public struct HTTPInfoResponse {
32 | public var couchdb: String!
33 | public var uuid: String!
34 | public var version: String!
35 |
36 | public init(data: Any) {
37 | if let d = data as? [String: Any] {
38 | if let
39 | couchdb = d["couchdb"] as? String,
40 | let uuid = d["uuid"] as? String,
41 | let version = d["version"] as? String {
42 | self.couchdb = couchdb
43 | self.uuid = uuid
44 | self.version = version
45 | }
46 | }
47 | }
48 | }
49 |
50 | public enum InfoResponse {
51 | case success(DataResponse, HTTPInfoResponse)
52 | case error(Error)
53 | }
54 |
55 | open func info(_ done: @escaping (InfoResponse) -> Void) {
56 | Alamofire.request(self.url, headers: self.headers).validate().responseJSON { response in
57 | switch response.result {
58 | case .failure(let error):
59 | done(.error(error))
60 | case .success:
61 | if let json = response.result.value {
62 | done(.success(response, HTTPInfoResponse(data: json)))
63 | return
64 | }
65 | }
66 | }
67 | }
68 |
69 |
70 |
71 | /**
72 | * Login
73 | *
74 | * http://docs.couchdb.org/en/latest/api/server/authn.html
75 | */
76 |
77 | /**
78 | * POST _session response
79 | *
80 | * http://docs.couchdb.org/en/latest/api/server/authn.html#post--_session
81 | */
82 | public struct HTTPPostSessionResponse {
83 | public var ok: Bool!
84 | public var name: String!
85 | public var roles: [String]!
86 |
87 | public init(data: Any) {
88 | if let dict = data as? [String: Any] {
89 | if let
90 | ok = dict["ok"] as? Bool,
91 | let name = dict["name"] as? String,
92 | let roles = dict["roles"] as? [String] {
93 | self.ok = ok
94 | self.name = name
95 | self.roles = roles
96 | }
97 | }
98 | }
99 | }
100 |
101 | public enum LoginResponse {
102 | case success(DataResponse, HTTPPostSessionResponse)
103 | case error(Error)
104 | }
105 |
106 | open func login(_ name: String, password: String, done: @escaping (LoginResponse) -> Void) {
107 | let data = [
108 | "name": name,
109 | "password": password
110 | ]
111 | Alamofire.request("\(self.url)_session", method: .post, parameters: data, encoding: JSONEncoding.default, headers: self.headers).validate().responseJSON { response in
112 | switch response.result {
113 | case .failure(let error):
114 | done(.error(error))
115 | case .success:
116 | if let json = response.result.value {
117 | done(.success(response, HTTPPostSessionResponse(data: json)))
118 | return
119 | }
120 | }
121 | }
122 | }
123 |
124 |
125 |
126 | /**
127 | * Get session
128 | *
129 | * http://docs.couchdb.org/en/latest/api/server/authn.html#get--_session
130 | */
131 |
132 | // http://docs.couchdb.org/en/latest/json-structure.html#user-context-object
133 | public struct UserContext {
134 | public var name: String!
135 | public var roles: [String]!
136 |
137 | public init(data: Any) {
138 | if let d = data as? [String: Any] {
139 | if let
140 | name = d["name"] as? String,
141 | let roles = d["roles"] as? [String] {
142 | self.name = name
143 | self.roles = roles
144 | }
145 | }
146 | }
147 | }
148 |
149 | public struct HTTPGetSessionResponseInfo {
150 | public var authenticated: String!
151 | public var authentication_db: String!
152 | public var authentication_handlers: [String]!
153 |
154 | public init(data: Any) {
155 | if let d = data as? [String: Any] {
156 | if let
157 | authenticated = d["authenticated"] as? String,
158 | let authentication_db = d["authentication_db"] as? String,
159 | let authentication_handlers = d["authentication_handlers"] as? [String] {
160 | self.authenticated = authenticated
161 | self.authentication_db = authentication_db
162 | self.authentication_handlers = authentication_handlers
163 | }
164 |
165 | }
166 | }
167 | }
168 |
169 | public struct HTTPGetSessionResponse {
170 | public var info: HTTPGetSessionResponseInfo!
171 | public var ok: Bool!
172 | public var userCtx: UserContext!
173 |
174 | public init(data: Any) {
175 | if let d = data as? [String: Any] {
176 | if let
177 | info = d["info"] as? [String: Any],
178 | let ok = d["ok"] as? Bool,
179 | let userCtx = d["userCtx"] as? [String: Any] {
180 | self.info = HTTPGetSessionResponseInfo(data: info)
181 | self.ok = ok
182 | self.userCtx = UserContext(data: userCtx)
183 | }
184 | }
185 | }
186 | }
187 |
188 | public enum GetSessionResponse {
189 | case success(DataResponse, HTTPGetSessionResponse)
190 | case error(Error)
191 | }
192 |
193 | open func getSession(_ done: @escaping (GetSessionResponse) -> Void) {
194 | Alamofire.request("\(self.url)_session", headers: self.headers).validate().responseJSON { response in
195 | switch response.result {
196 | case .failure(let error):
197 | done(.error(error))
198 | case .success:
199 | if let json = response.result.value {
200 | done(.success(response, HTTPGetSessionResponse(data: json)))
201 | return
202 | }
203 | }
204 | }
205 | }
206 |
207 |
208 |
209 | /**
210 | * Logout
211 | *
212 | * http://docs.couchdb.org/en/latest/api/server/authn.html#delete--_session
213 | */
214 | public struct HTTPDeleteSessionResponse {
215 | public var ok: Bool!
216 |
217 | public init(data: Any) {
218 | if let d = data as? [String: Any] {
219 | if let ok = d["ok"] as? Bool {
220 | self.ok = ok
221 | }
222 | }
223 | }
224 | }
225 |
226 | public enum LogoutResponse {
227 | case success(DataResponse, HTTPDeleteSessionResponse)
228 | case error(Error)
229 | }
230 |
231 | open func logout(_ done: @escaping (LogoutResponse) -> Void) {
232 | Alamofire.request("\(self.url)_session", method: .delete, headers: self.headers).validate().responseJSON { response in
233 | switch response.result {
234 | case .failure(let error):
235 | done(.error(error))
236 | case .success:
237 | if let json = response.result.value {
238 | done(.success(response, HTTPDeleteSessionResponse(data: json)))
239 | return
240 | }
241 | }
242 | }
243 | }
244 |
245 |
246 |
247 | /**
248 | * Create database
249 | *
250 | * http://docs.couchdb.org/en/latest/api/database/common.html#put--db
251 | */
252 |
253 | public struct HTTPPutCreateSuccess {
254 | public var ok: Bool!
255 |
256 | public init(data: Any) {
257 | if let dict = data as? [String: Any] {
258 | if
259 | let ok = dict["ok"] as? Bool {
260 | self.ok = ok
261 | }
262 | }
263 | }
264 | }
265 |
266 | public enum CreateDatabaseResponse {
267 | case success(DataResponse, HTTPPutCreateSuccess)
268 | case error(Error)
269 | }
270 |
271 | open func createDatabase(_ database: String, done: @escaping (CreateDatabaseResponse) -> Void) {
272 | Alamofire.request("\(self.url)\(database)", method: .put, headers: self.headers).validate().responseJSON { response in
273 | switch response.result {
274 | case .failure(let error):
275 | done(.error(error))
276 | case .success:
277 | if let json = response.result.value {
278 | done(.success(response, HTTPPutCreateSuccess(data: json)))
279 | return
280 | }
281 | }
282 | }
283 | }
284 |
285 |
286 |
287 | /**
288 | * Delete database
289 | *
290 | * http://docs.couchdb.org/en/latest/api/database/common.html#delete--db
291 | */
292 |
293 | public struct HTTPDeleteResponse {
294 | public var ok: Bool!
295 |
296 | public init(data: Any) {
297 | if let dict = data as? [String: Any] {
298 | if let ok = dict["ok"] as? Bool {
299 | self.ok = ok
300 | }
301 | }
302 | }
303 | }
304 |
305 | public enum DeleteDatabaseReponse {
306 | case success(DataResponse, HTTPDeleteResponse)
307 | case error(Error)
308 | }
309 |
310 | open func deleteDatabase(_ database: String, done: @escaping (DeleteDatabaseReponse) -> Void) {
311 | Alamofire.request("\(self.url)\(database)", method: .delete, headers: self.headers).validate().responseJSON { response in
312 | switch response.result {
313 | case .failure(let error):
314 | done(.error(error))
315 | case .success:
316 | if let json = response.result.value {
317 | done(.success(response, HTTPDeleteResponse(data: json)))
318 | return
319 | }
320 | }
321 |
322 | }
323 | }
324 |
325 |
326 |
327 | /**
328 | * Create user
329 | */
330 |
331 | /**
332 | * User struct
333 | *
334 | * http://docs.couchdb.org/en/latest/intro/security.html#creating-new-user
335 | */
336 | public struct User {
337 | public var name: String
338 | public var password: String
339 | public var roles: [String]
340 | fileprivate let type: String = "user"
341 |
342 | public init(name: String, password: String, roles: [String]) {
343 | self.name = name
344 | self.password = password
345 | self.roles = roles
346 | }
347 |
348 | public func serialize() -> [String: Any] {
349 | var dict = [String: Any]()
350 | dict["name"] = name as String?
351 | dict["password"] = password as String?
352 | dict["roles"] = roles as [String]?
353 | dict["type"] = type as String?
354 | return dict
355 | }
356 | }
357 |
358 | /**
359 | * Create user in db
360 | */
361 | open func createUser(_ user: User, done: @escaping (Database.PostResponse) -> Void) {
362 | let data = user.serialize()
363 | Alamofire.request("\(self.url)_users/org.couchdb.user:\(user.name)", method: .put, parameters: data, encoding: JSONEncoding.default, headers: self.headers).validate().responseJSON { response in
364 | switch response.result {
365 | case .failure(let error):
366 | done(.error(error))
367 | case .success:
368 | if let json = response.result.value {
369 | done(.success(response, Database.HTTPPostDatabaseReponse(data: json)))
370 | return
371 | }
372 | }
373 | }
374 | }
375 |
376 |
377 |
378 | /**
379 | * Use database
380 | */
381 | open func use(_ name: String) -> Database {
382 | return Database(url: "\(self.url)\(name)", headers: self.headers)
383 | }
384 |
385 |
386 |
387 | /**
388 | * Document
389 | */
390 | open class Document {
391 |
392 | open var dictionary = [String: Any]()
393 | open var _id: String?
394 | open var _rev: String?
395 |
396 | public init(_id: String?, _rev: String?) {
397 | self._id = _id
398 | self._rev = _rev
399 | }
400 |
401 | public init(data: [String: Any]) {
402 | if let
403 | _id = data["_id"] as? String,
404 | let _rev = data["_rev"] as? String {
405 | self._id = _id
406 | self._rev = _rev
407 | }
408 | }
409 |
410 | open func serialize() -> [String: Any] {
411 | self.dictionary["_id"] = self._id as String?
412 | self.dictionary["_rev"] = self._rev as String?
413 | return self.dictionary
414 | }
415 | }
416 |
417 |
418 |
419 | /**
420 | * Design document
421 | */
422 | open class DesignDocument: Document {
423 |
424 | open let language: String = "javascript"
425 | open var views: [String: DesignDocumentView]
426 |
427 | public init(_id: String?, _rev: String?, views: [String: DesignDocumentView]) {
428 | self.views = views
429 | super.init(_id: "_design/\(_id!)", _rev: _rev)
430 | }
431 |
432 | open override func serialize() -> [String : Any] {
433 | self.dictionary["language"] = language as String?
434 | var wrapper = [String: Any]()
435 | for (key, value) in self.views {
436 | var _views = ["map": value.map]
437 | if let reduce = value.reduce {
438 | _views["reduce"] = reduce
439 | }
440 | wrapper[key] = _views
441 | }
442 | self.dictionary["views"] = wrapper
443 | return super.serialize()
444 | }
445 |
446 | }
447 |
448 |
449 |
450 | /**
451 | * View
452 | */
453 | open class DesignDocumentView {
454 | open var map: String
455 | open var reduce: String?
456 |
457 | public init(map: String, reduce: String?) {
458 | self.map = map
459 | self.reduce = reduce
460 | }
461 |
462 | }
463 |
464 |
465 |
466 | /**
467 | * Query params
468 | *
469 | * http://docs.couchdb.org/en/latest/api/ddoc/views.html#get--db-_design-ddoc-_view-view
470 | */
471 | open class QueryParameters: QueryString {
472 |
473 | open var conflicts: Bool?
474 | open var descending: Bool?
475 | open var endkey: String?
476 | open var endkey_docid: String?
477 | open var group: Bool?
478 | open var group_level: Int?
479 | open var include_docs: Bool?
480 | open var attachments: Bool?
481 | open var att_encoding_info: Bool?
482 | open var inclusive_end: Bool?
483 | open var key: String?
484 | open var keys: [String]?
485 | open var limit: Int?
486 | open var reduce: Bool?
487 | open var skip: Int?
488 | open var stale: String?
489 | open var startkey: String?
490 | open var startkey_docid: String?
491 | open var update_seq: Bool?
492 |
493 | public override init() {
494 | super.init()
495 | }
496 |
497 | }
498 |
499 |
500 |
501 | /**
502 | * Database
503 | */
504 | open class Database {
505 |
506 | fileprivate var url: String
507 | fileprivate var headers: [String: String]?
508 |
509 | public init(url: String, headers: [String: String]?) {
510 | self.url = url.hasSuffix("/") ? url : "\(url)/"
511 | self.headers = headers
512 | }
513 |
514 |
515 | /**
516 | * Create document
517 | *
518 | * http://docs.couchdb.org/en/latest/api/database/common.html#post--db
519 | */
520 | public struct HTTPPostDatabaseReponse {
521 | public var id: String!
522 | public var ok: Bool!
523 | public var rev: String!
524 |
525 | public init(data: Any) {
526 | if let dict = data as? [String: Any] {
527 | if
528 | let id = dict["id"] as? String,
529 | let ok = dict["ok"] as? Bool,
530 | let rev = dict["rev"] as? String {
531 | self.id = id
532 | self.ok = ok
533 | self.rev = rev
534 | }
535 | }
536 | }
537 | }
538 |
539 | public enum PostResponse {
540 | case success(DataResponse, HTTPPostDatabaseReponse)
541 | case error(Error)
542 | }
543 |
544 | open func post(_ document: Document, done: @escaping (PostResponse) -> Void) {
545 | Alamofire.request(self.url, method: .post, parameters: document.serialize(), encoding: JSONEncoding.default, headers: self.headers).validate().responseJSON { response in
546 | switch response.result {
547 | case .failure(let error):
548 | done(.error(error))
549 | case .success:
550 | if let json = response.result.value {
551 | done(.success(response, HTTPPostDatabaseReponse(data: json)))
552 | return
553 | }
554 | }
555 | }
556 | }
557 |
558 | /**
559 | * Edit document or create new one with id
560 | *
561 | * http://docs.couchdb.org/en/latest/api/document/common.html#put--db-docid
562 | */
563 | open func put(_ document: Document, done: @escaping (PostResponse) -> Void) {
564 | Alamofire.request("\(self.url)\(document._id!)", method: .put, parameters: document.serialize(), encoding: JSONEncoding.default, headers: self.headers).validate().responseJSON { response in
565 | switch response.result {
566 | case .failure(let error):
567 | done(.error(error))
568 | case .success:
569 | if let json = response.result.value {
570 | done(.success(response, HTTPPostDatabaseReponse(data: json)))
571 | return
572 | }
573 | }
574 | }
575 | }
576 |
577 |
578 |
579 | /**
580 | * Delete document
581 | *
582 | * http://docs.couchdb.org/en/latest/api/document/common.html#delete--db-docid
583 | */
584 | open func delete(_ document: Document, done: @escaping (PostResponse) -> Void) {
585 | Alamofire.request("\(self.url)\(document._id!)?rev=\(document._rev!)", method: .delete, headers: self.headers).validate().responseJSON { response in
586 | switch response.result {
587 | case .failure(let error):
588 | done(.error(error))
589 | case .success:
590 | if let json = response.result.value {
591 | done(.success(response, HTTPPostDatabaseReponse(data: json)))
592 | return
593 | }
594 | }
595 | }
596 | }
597 |
598 |
599 |
600 | /**
601 | * Get document
602 | *
603 | * http://docs.couchdb.org/en/latest/api/document/common.html#get--db-docid
604 | */
605 | public enum GetResponse {
606 | case success(DataResponse, Any)
607 | case error(Error)
608 | }
609 |
610 |
611 | open func get(_ id: String, done: @escaping (GetResponse) -> Void) {
612 | Alamofire.request("\(self.url)\(id)", headers: self.headers).validate().responseJSON { response in
613 | switch response.result {
614 | case .failure(let error):
615 | done(.error(error))
616 | case .success:
617 | if let json = response.result.value {
618 | done(.success(response, json))
619 | return
620 | }
621 | }
622 | }
623 | }
624 |
625 |
626 |
627 | /**
628 | * Create multiple documents with a single request
629 | *
630 | * http://docs.couchdb.org/en/latest/api/database/bulk-api.html
631 | */
632 | public struct HTTPBulkResponse {
633 | public var id: String!
634 | public var rev: String!
635 | public var error: String?
636 | public var reason: String?
637 |
638 | public init(data: Any) {
639 | if let dict = data as? [String: Any] {
640 | if
641 | let id = dict["id"] as? String,
642 | let rev = dict["rev"] as? String {
643 | self.id = id
644 | self.rev = rev
645 | }
646 | if let error = dict["error"] as? String {
647 | self.error = error
648 | }
649 | if let reason = dict["reason"] as? String {
650 | self.reason = reason
651 | }
652 | }
653 | }
654 |
655 | }
656 |
657 | public enum BulkResponse {
658 | case success(DataResponse, [HTTPBulkResponse])
659 | case error(Error)
660 | }
661 |
662 | open func bulk(_ documents: [Document], done: @escaping (BulkResponse) -> Void) {
663 | let docs = documents.map() { $0.serialize() }
664 | let data = [
665 | "docs": docs
666 | ]
667 | Alamofire.request("\(self.url)_bulk_docs", method: .post, parameters: data, encoding: JSONEncoding.default, headers: self.headers).validate().responseJSON { response in
668 | switch response.result {
669 | case .failure(let error):
670 | done(.error(error))
671 | case .success:
672 | if let json = response.result.value {
673 | if let data = json as? [Any] {
674 | let arr = data.map() { HTTPBulkResponse(data: $0) }
675 | done(.success(response, arr))
676 | }
677 | }
678 | }
679 | }
680 | }
681 |
682 |
683 |
684 | /**
685 | * Use certain view (design document)
686 | */
687 | open func view(_ name: String) -> View {
688 | return View(url: "\(self.url)_design/\(name)/", headers: self.headers)
689 | }
690 |
691 | }
692 |
693 |
694 |
695 | /**
696 | * View
697 | */
698 | open class View {
699 |
700 | /**
701 | * http://docs.couchdb.org/en/latest/api/ddoc/views.html#get--db-_design-ddoc-_view-view
702 | */
703 | public struct GETResponse {
704 | public var offset: Int!
705 | public var rows: [Row]!
706 | public var total_rows: Int!
707 | public var update_seq: Int!
708 |
709 | public init(data: Any) {
710 | if let dict = data as? [String: Any] {
711 | if
712 | let offset = dict["offset"] as? Int,
713 | let rows = dict["rows"] as? [Any],
714 | let total_rows = dict["total_rows"] as? Int {
715 | self.offset = offset
716 | self.total_rows = total_rows
717 | self.rows = []
718 | for row in rows {
719 | self.rows.append(Row(data: row))
720 | }
721 | }
722 | if let update_seq = dict["update_seq"] as? Int {
723 | self.update_seq = update_seq
724 | }
725 | }
726 | }
727 | }
728 |
729 | public struct Row {
730 | public var id: String!
731 | public var key: String!
732 | public var value: Any!
733 | public var doc: [String: Any]?
734 |
735 | public init(data: Any) {
736 | if let dict = data as? [String: Any] {
737 | if
738 | let id = dict["id"] as? String,
739 | let key = dict["key"] as? String {
740 | self.id = id
741 | self.key = key
742 | self.value = dict["value"]
743 | }
744 | if let doc = dict["doc"] as? [String: Any] {
745 | self.doc = doc
746 | }
747 | }
748 | }
749 | }
750 |
751 | fileprivate var url: String
752 | fileprivate var headers: [String: String]?
753 |
754 | public init(url: String, headers: [String: String]?) {
755 | self.url = url.hasSuffix("/") ? url : "\(url)/"
756 | self.headers = headers
757 | }
758 |
759 | public enum Response {
760 | case success(DataResponse, GETResponse)
761 | case error(Error)
762 | }
763 |
764 | open func get(_ name: String, query: QueryParameters, done: @escaping (Response) -> Void) {
765 | let params = query.encode().addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
766 | Alamofire.request("\(self.url)_view/\(name)?\(params)", headers: self.headers).validate().responseJSON { response in
767 | switch response.result {
768 | case .failure(let error):
769 | done(.error(error))
770 | case .success:
771 | if let json = response.result.value {
772 | done(.success(response, GETResponse(data: json)))
773 | return
774 | }
775 | }
776 | }
777 | }
778 | }
779 |
780 |
781 | }
782 |
783 |
784 |
785 |
786 |
787 |
788 |
789 |
790 |
791 |
792 |
793 |
794 |
795 |
796 |
--------------------------------------------------------------------------------
/swift-couchdb/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "ipad",
35 | "size" : "29x29",
36 | "scale" : "1x"
37 | },
38 | {
39 | "idiom" : "ipad",
40 | "size" : "29x29",
41 | "scale" : "2x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "40x40",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "40x40",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "76x76",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "76x76",
61 | "scale" : "2x"
62 | }
63 | ],
64 | "info" : {
65 | "version" : 1,
66 | "author" : "xcode"
67 | }
68 | }
--------------------------------------------------------------------------------
/swift-couchdb/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 | UIInterfaceOrientationLandscapeLeft
37 | UIInterfaceOrientationLandscapeRight
38 |
39 | UISupportedInterfaceOrientations~ipad
40 |
41 | UIInterfaceOrientationPortrait
42 | UIInterfaceOrientationPortraitUpsideDown
43 | UIInterfaceOrientationLandscapeLeft
44 | UIInterfaceOrientationLandscapeRight
45 |
46 | NSAppTransportSecurity
47 |
48 |
49 | NSAllowsArbitraryLoads
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/swift-couchdb/MyDocument.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | open class MyDocument: CouchDB.Document {
5 |
6 | open var city: String?
7 |
8 | public init(city: String, _id: String?, _rev: String?) {
9 | self.city = city
10 | super.init(_id: _id, _rev: _rev)
11 | }
12 |
13 | public override init(data: [String: Any]) {
14 | if let city = data["city"] as? String {
15 | self.city = city
16 | }
17 | super.init(data: data)
18 | }
19 |
20 | open override func serialize() -> [String: Any] {
21 | self.dictionary["city"] = self.city as AnyObject?
22 | return super.serialize()
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/swift-couchdb/QueryString.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 |
5 |
6 | /**
7 | * Query string
8 | */
9 | open class QueryString {
10 |
11 |
12 |
13 | public init() {
14 |
15 | }
16 |
17 |
18 |
19 | /**
20 | * encode
21 | */
22 | open func encode() -> String {
23 |
24 | let mirror = Mirror(reflecting: self)
25 | var params = [String]()
26 |
27 | for (label, value) in mirror.children {
28 |
29 | if type(of: (value)) is String.Type {
30 | params.append(handleString(label!, value: value))
31 | }
32 |
33 | else if type(of: (value)) is Bool.Type {
34 | params.append("\(label!)=\(value)")
35 | }
36 |
37 | else if type(of: (value)) is Int.Type {
38 | params.append(handleInt(label!, value: value))
39 | }
40 |
41 | else if type(of: (value)) is [String].Type {
42 | if let arr = value as? [String] {
43 | let vals = arr.map() {"\"\($0)\""}
44 | let values = vals.joined(separator: ",")
45 | params.append("\(label!)=[\(values)]")
46 | }
47 | }
48 |
49 | else {
50 | // handle optionals
51 | let sub = Mirror(reflecting: value)
52 |
53 | if let displayStyle = sub.displayStyle {
54 | switch displayStyle {
55 | case .optional:
56 |
57 | for (subLabel, subValue) in sub.children {
58 |
59 | if let subLabel = subLabel {
60 | if subLabel == "some" {
61 |
62 | if type(of: (subValue)) is String.Type {
63 | params.append(handleString(label!, value: subValue))
64 | }
65 |
66 | else if type(of: (subValue)) is Int.Type {
67 | params.append(handleInt(label!, value: subValue))
68 | }
69 |
70 | else if type(of: (subValue)) is Bool.Type {
71 | params.append("\(label!)=\(subValue)")
72 | }
73 | }
74 | }
75 |
76 | }
77 |
78 | default:
79 | break
80 | }
81 | }
82 |
83 | }
84 | }
85 |
86 | return params.joined(separator: "&")
87 |
88 | }
89 |
90 | // handle String
91 | fileprivate func handleString(_ key: String, value: Any) -> String {
92 | return "\(key)=\"\(value)\""
93 | }
94 |
95 | fileprivate func handleInt(_ key: String, value: Any) -> String {
96 | return "\(key)=\(value)"
97 | }
98 |
99 | }
100 |
--------------------------------------------------------------------------------
/swift-couchdb/ViewController.swift:
--------------------------------------------------------------------------------
1 |
2 | import UIKit
3 |
4 | //public class MyDocument: Document {
5 | //
6 | // public var city: String!
7 | //
8 | // public init(city: String, _id: String?, _rev: String?) {
9 | // self.city = city
10 | // super.init(_id: _id, _rev: _rev)
11 | // }
12 | //
13 | // public override init(data: AnyObject) {
14 | // if let city = data["city"] as? String {
15 | // self.city = city
16 | // }
17 | // super.init(data: data)
18 | // }
19 | //
20 | // public override func serialize() -> [String: AnyObject] {
21 | // self.dictionary["city"] = self.city
22 | // return super.serialize()
23 | // }
24 | //
25 | //}
26 |
27 | class ViewController: UIViewController {
28 |
29 | override func viewDidLoad() {
30 | super.viewDidLoad()
31 | // Do any additional setup after loading the view, typically from a nib.
32 |
33 | // var couchdb = CouchDB(url: "http://localhost:5984", name: nil, password: nil)
34 |
35 | // var john = CouchDB.User(name: "john", password: "secret", roles: ["awesome"])
36 | // couchdb.createUser(john) { response in
37 | // switch response {
38 | // case .Error(let error):
39 | // println(error)
40 | // case .Success(let res):
41 | // println(res.id)
42 | // println(res.ok)
43 | // println(res.rev)
44 | // }
45 | // }
46 |
47 | // couchdb.create("tight") { response in
48 | // switch response {
49 | // case .Error(let error):
50 | // println(error)
51 | // case .Failure(let failure):
52 | // println(failure.error)
53 | // println(failure.reason)
54 | // case .Success(let response):
55 | // println(response.ok)
56 | // }
57 | // }
58 |
59 | // couchdb.delete("nice") { response in
60 | // switch response {
61 | // case .Error(let error):
62 | // println(error)
63 | // case .Success(let res):
64 | // println(res.ok)
65 | // }
66 | // }
67 |
68 | // login
69 | // couchdb.login() { response in
70 | // switch response {
71 | // case .Error(let error):
72 | // println(error)
73 | // case .Success(let response):
74 | // println(response)
75 | // println(response.name)
76 | // println(response.ok)
77 | // println(response.roles)
78 | // }
79 | // }
80 |
81 | // var database = couchdb.use("awesome")
82 | //
83 | // create document
84 | // var doc = MyDocument(city: "darmstadt", _id: "tight", _rev: nil)
85 | // var doc = MyDocument(city: "berlin", _id: nil, _rev: nil)
86 | // database.post(doc) { response in
87 | // switch response {
88 | // case .Error(let error):
89 | // println(error)
90 | // case .Success(let res):
91 | // println(res.id)
92 | // println(res.ok)
93 | // println(res.rev)
94 | // }
95 | // }
96 |
97 | // get document
98 | // var doc: MyDocument!
99 | // database.get("tight") { response in
100 | // switch response {
101 | // case .Error(let error):
102 | // println(error)
103 | // case .Success(let data):
104 | // println(data)
105 | // doc = MyDocument(data: data)
106 | //
107 | // // edit document
108 | // doc.city = "Frankfurt"
109 | // database.put(doc) { response in
110 | // switch response {
111 | // case .Error(let error):
112 | // println(error)
113 | // case .Success(let res):
114 | // println(res.id)
115 | // println(res.ok)
116 | // println(res.rev)
117 | // }
118 | // }
119 |
120 | // // delete document
121 | // database.delete(doc) { response in
122 | // switch response {
123 | // case .Error(let error):
124 | // println(error)
125 | // case .Success(let res):
126 | // println(res.id)
127 | // println(res.rev)
128 | // println(res.ok)
129 | // }
130 | // }
131 | // }
132 | // }
133 |
134 | // var citiesByName = "function(doc) {if (doc.city) {emit(doc.city)}}"
135 | // var myView = View(map: citiesByName, reduce: nil)
136 | //
137 | // var design = DesignDocument(_id: "cities", _rev: nil, views: [
138 | // "citiesByName": myView
139 | // ])
140 | //
141 | // database.put(design) { response in
142 | // switch response {
143 | // case .Error(let error):
144 | // println(error)
145 | // case .Success(let res):
146 | // println(res.id)
147 | // println(res.ok)
148 | // println(res.rev)
149 | // }
150 | //
151 | // }
152 |
153 | // var test = QueryParameters()
154 | // test.descending = true
155 | // test.endkey = "awesome"
156 | // test.keys = ["one", "two", "three"]
157 | // var q = test.encode()
158 | // println(q)
159 | // println(q.stringByAddingPercentEncodingWithAllowedCharacters(.URLQueryAllowedCharacterSet())!)
160 |
161 |
162 | // // query view
163 | // var view = database.view("cities")
164 | //
165 | // var params = QueryParameters()
166 | // params.limit = 3
167 | // params.descending = true
168 | // view.get("citiesByName", query: params) { response in
169 | // switch response {
170 | // case .Error(let error):
171 | // println(error)
172 | // case .Success(let res):
173 | // println(res.offset)
174 | // println(res.total_rows)
175 | // for row in res.rows {
176 | // println(row.id)
177 | // println(row.key)
178 | // }
179 | // }
180 | // }
181 | }
182 |
183 | override func didReceiveMemoryWarning() {
184 | super.didReceiveMemoryWarning()
185 | // Dispose of any resources that can be recreated.
186 | }
187 |
188 |
189 | }
190 |
191 |
--------------------------------------------------------------------------------
/swift-couchdbTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/swift-couchdbTests/swift_couchdbTests.swift:
--------------------------------------------------------------------------------
1 |
2 | import UIKit
3 | import XCTest
4 | import swift_couchdb
5 |
6 | fileprivate let url = "http://localhost:5984"
7 |
8 | class swift_couchdbTests: XCTestCase {
9 |
10 | fileprivate let timeout: TimeInterval = 1
11 | fileprivate var couchdb = CouchDB(url: url, name: nil, password: nil)
12 |
13 | override func setUp() {
14 | super.setUp()
15 | // Put setup code here. This method is called before the invocation of each test method in the class.
16 | }
17 |
18 | override func tearDown() {
19 | // Put teardown code here. This method is called after the invocation of each test method in the class.
20 | super.tearDown()
21 | }
22 |
23 |
24 |
25 | func testCreateDatabase() {
26 | let expectation = self.expectation(description: "create database")
27 | let name = "test-create-database"
28 | couchdb.createDatabase(name) { response in
29 | switch response {
30 | case .error(let error):
31 | XCTAssertNil(error)
32 | case .success(let response, let success):
33 | XCTAssertEqual(response.response?.statusCode, 201)
34 | XCTAssert(success.ok!)
35 | }
36 | self.couchdb.deleteDatabase(name) { _ in
37 | expectation.fulfill()
38 | }
39 |
40 | }
41 | waitForExpectations(timeout: timeout, handler: nil)
42 | }
43 |
44 |
45 |
46 | func testDeleteDatabase() {
47 | let expectation = self.expectation(description: "delete database")
48 | let name = "test-delete-database"
49 | couchdb.createDatabase(name) { _ in
50 | self.couchdb.deleteDatabase(name) { response in
51 | switch response {
52 | case .error(let error):
53 | XCTAssertNil(error)
54 | case .success(let response, let success):
55 | XCTAssertEqual(response.response?.statusCode, 200)
56 | XCTAssert(success.ok!)
57 | }
58 | expectation.fulfill()
59 | }
60 | }
61 | waitForExpectations(timeout: timeout, handler: nil)
62 | }
63 |
64 |
65 |
66 | func testCreateDocument() {
67 | let expectation = self.expectation(description: "create document")
68 | let name = "test-create-document"
69 | couchdb.createDatabase(name) { _ in
70 | let database = self.couchdb.use(name)
71 | let doc = MyDocument(city: "darmstadt", _id: "home", _rev: nil)
72 | database.post(doc) { response in
73 | switch response {
74 | case .error(let error):
75 | XCTAssertNil(error)
76 | case .success(let response, let success):
77 | XCTAssertEqual(response.response?.statusCode, 201)
78 | XCTAssert(success.ok!)
79 | }
80 | self.couchdb.deleteDatabase(name) { _ in
81 | expectation.fulfill()
82 | }
83 | }
84 | }
85 | waitForExpectations(timeout: timeout, handler: nil)
86 | }
87 |
88 |
89 |
90 | func testGetDocument() {
91 | let expectation = self.expectation(description: "get document")
92 | let name = "test-get-document"
93 | couchdb.createDatabase(name) { _ in
94 | let database = self.couchdb.use(name)
95 | let doc = MyDocument(city: "darmstadt", _id: "home", _rev: nil)
96 | database.post(doc) { _ in
97 | database.get("home") { response in
98 | switch response {
99 | case .error(let error):
100 | XCTAssertNil(error)
101 | case .success(let response, let data):
102 | XCTAssertEqual(response.response?.statusCode, 200)
103 | let doc = MyDocument(data: data as! [String : Any])
104 | XCTAssertEqual(doc.city, "darmstadt")
105 | }
106 | self.couchdb.deleteDatabase(name) { _ in
107 | expectation.fulfill()
108 | }
109 | }
110 |
111 | }
112 | }
113 | waitForExpectations(timeout: timeout, handler: nil)
114 | }
115 |
116 |
117 |
118 | func testDeleteDocument() {
119 | let expectation = self.expectation(description: "delete document")
120 | let name = "test-delete-document"
121 | couchdb.createDatabase(name) { _ in
122 | let database = self.couchdb.use(name)
123 | let doc = MyDocument(city: "darmstadt", _id: nil, _rev: nil)
124 | database.post(doc) { res in
125 | switch res {
126 | case .error(let error):
127 | XCTAssertNil(error)
128 | case .success(let response, let success):
129 | XCTAssertEqual(response.response?.statusCode, 201)
130 | doc._id = success.id
131 | doc._rev = success.rev
132 | database.delete(doc) { success in
133 | switch success {
134 | case .error(let error):
135 | XCTAssertNil(error)
136 | case .success(let response, let success):
137 | XCTAssertEqual(response.response?.statusCode, 200)
138 | XCTAssert(success.ok!)
139 | }
140 | self.couchdb.deleteDatabase(name) { _ in
141 | expectation.fulfill()
142 | }
143 | }
144 | }
145 | }
146 | }
147 | waitForExpectations(timeout: timeout, handler: nil)
148 | }
149 |
150 |
151 |
152 | func testEditDocument() {
153 | let expectation = self.expectation(description: "edit document")
154 | let name = "test-edit-document"
155 | couchdb.createDatabase(name) { _ in
156 | let database = self.couchdb.use(name)
157 | let doc = MyDocument(city: "darmstadt", _id: "edit", _rev: nil)
158 | database.post(doc) { _ in
159 | database.get("edit") { response in
160 | switch response {
161 | case .error(let error):
162 | XCTAssertNil(error)
163 | case .success(let response, let success):
164 | XCTAssertEqual(response.response?.statusCode, 200)
165 | let docWithRev = MyDocument(data: success as! [String : Any])
166 | docWithRev.city = "frankfurt"
167 | database.put(docWithRev) { res in
168 | switch res {
169 | case .error(let error):
170 | XCTAssertNil(error)
171 | case .success(let response, let success):
172 | XCTAssertEqual(response.response?.statusCode, 201)
173 | XCTAssert(success.ok!)
174 | }
175 | self.couchdb.deleteDatabase(name) { _ in
176 | expectation.fulfill()
177 | }
178 | }
179 | }
180 | }
181 | }
182 | }
183 | waitForExpectations(timeout: timeout, handler: nil)
184 | }
185 |
186 |
187 |
188 | func testCreateBulkDocuments() {
189 | let berlin = MyDocument(city: "berlin", _id: nil, _rev: nil)
190 | let frankfurt = MyDocument(city: "frankfurt", _id: nil, _rev: nil)
191 | let munich = MyDocument(city: "munich", _id: nil, _rev: nil)
192 | let duesseldorf = MyDocument(city: "duesseldorf", _id: nil, _rev: nil)
193 | let darmstadt = MyDocument(city: "darmstadt", _id: nil, _rev: nil)
194 |
195 | let expectation = self.expectation(description: "bulk documents")
196 | let name = "bulk-documents"
197 |
198 | couchdb.createDatabase(name) { _ in
199 | let database = self.couchdb.use(name)
200 | database.bulk([berlin, frankfurt, munich, duesseldorf, darmstadt]) { response in
201 | switch response {
202 | case .error(let error):
203 | XCTAssertNil(error)
204 | case .success(let response, let data):
205 | XCTAssertEqual(response.response?.statusCode, 201)
206 | for datum in data {
207 | XCTAssertNotNil(datum.id)
208 | }
209 | }
210 | self.couchdb.deleteDatabase(name) { _ in
211 | expectation.fulfill()
212 | }
213 | }
214 | }
215 | waitForExpectations(timeout: timeout, handler: nil)
216 | }
217 |
218 |
219 |
220 | func testCreateDesignDocument() {
221 | let expectation = self.expectation(description: "create design document")
222 | let name = "create-design-document"
223 |
224 | // create design document
225 | let map = "function(doc) { if (doc.city) { emit(doc.city) } }"
226 | let view = CouchDB.DesignDocumentView(map: map, reduce: nil)
227 | let designDocument = CouchDB.DesignDocument(_id: "cities", _rev: nil, views: [
228 | "byName": view
229 | ])
230 |
231 | // add document to db
232 | couchdb.createDatabase(name) { _ in
233 | let database = self.couchdb.use(name)
234 | database.put(designDocument) { response in
235 | switch response {
236 | case .error(let error):
237 | XCTAssertNil(error)
238 | case .success(let response, let success):
239 | XCTAssertEqual(response.response?.statusCode, 201)
240 | XCTAssert(success.ok!)
241 | }
242 | self.couchdb.deleteDatabase(name) { _ in
243 | expectation.fulfill()
244 | }
245 | }
246 | }
247 |
248 | waitForExpectations(timeout: timeout, handler: nil)
249 |
250 | }
251 |
252 |
253 |
254 | func testQueryView() {
255 | let expectation = self.expectation(description: "query view")
256 | let name = "test-query-view"
257 |
258 | // create design document
259 | let map = "function(doc) { if (doc.city) { emit(doc.city) } }"
260 | let view = CouchDB.DesignDocumentView(map: map, reduce: nil)
261 | let designDocument = CouchDB.DesignDocument(_id: "cities", _rev: nil, views: [
262 | "byName": view
263 | ])
264 |
265 | // add design document to db
266 | couchdb.createDatabase(name) { _ in
267 | let database = self.couchdb.use(name)
268 | database.put(designDocument) { _ in
269 |
270 | // add some dummy documents
271 | let berlin = MyDocument(city: "berlin", _id: nil, _rev: nil)
272 | let frankfurt = MyDocument(city: "frankfurt", _id: nil, _rev: nil)
273 | let munich = MyDocument(city: "munich", _id: nil, _rev: nil)
274 | let duesseldorf = MyDocument(city: "duesseldorf", _id: nil, _rev: nil)
275 | let darmstadt = MyDocument(city: "darmstadt", _id: nil, _rev: nil)
276 |
277 | database.bulk([berlin, frankfurt, munich, duesseldorf, darmstadt]) { _ in
278 |
279 | // query view
280 | let view = database.view("cities")
281 | let params = CouchDB.QueryParameters()
282 | params.limit = 3
283 | params.descending = true
284 | view.get("byName", query: params) { response in
285 | switch response {
286 | case .error(let error):
287 | XCTAssertNil(error)
288 | case .success(let result, let response):
289 | XCTAssertEqual(result.response?.statusCode, 200)
290 | XCTAssertEqual(response.rows.count, 3)
291 | XCTAssertEqual(response.rows[0].key, "munich")
292 | }
293 | self.couchdb.deleteDatabase(name) { _ in
294 | expectation.fulfill()
295 | }
296 | }
297 |
298 | }
299 |
300 | }
301 | }
302 |
303 | waitForExpectations(timeout: timeout, handler: nil)
304 | }
305 |
306 |
307 |
308 | func testCreateUser() {
309 | let expectation = self.expectation(description: "create user")
310 |
311 | let john = CouchDB.User(name: "john", password: "secret", roles: ["awesome"])
312 | couchdb.createUser(john) { response in
313 | switch response {
314 | case .error(let error):
315 | XCTAssertNil(error)
316 | case .success(let response, let res):
317 | XCTAssertEqual(response.response?.statusCode, 201)
318 | XCTAssert(res.ok!)
319 | }
320 | expectation.fulfill()
321 | }
322 |
323 | waitForExpectations(timeout: timeout, handler: nil)
324 | }
325 |
326 |
327 |
328 | func testDeleteUser() {
329 | let expectation = self.expectation(description: "delete user")
330 |
331 | // create user
332 | let john = CouchDB.User(name: "john", password: "secret", roles: ["awesome"])
333 | couchdb.createUser(john) { _ in
334 |
335 | // delete user
336 | let database = self.couchdb.use("_users")
337 | database.get("org.couchdb.user:john") { response in
338 | switch response {
339 | case .error(let error):
340 | XCTAssertNil(error)
341 | case .success(let response, let json):
342 | XCTAssertEqual(response.response?.statusCode, 200)
343 | let doc = CouchDB.Document(data: json as! [String : Any])
344 |
345 | database.delete(doc) { res in
346 | switch res {
347 | case .error(let error):
348 | XCTAssertNil(error)
349 | case .success(let response, let success):
350 | XCTAssertEqual(response.response?.statusCode, 200)
351 | XCTAssert(success.ok!)
352 | }
353 | expectation.fulfill()
354 | }
355 |
356 | }
357 | }
358 |
359 | }
360 |
361 | waitForExpectations(timeout: timeout, handler: nil)
362 | }
363 |
364 |
365 |
366 | func testLogin() {
367 | let expectation = self.expectation(description: "login")
368 |
369 | // create user first
370 | let steve = CouchDB.User(name: "steve", password: "password", roles: ["awesome"])
371 | couchdb.createUser(steve) { _ in
372 |
373 | // test login
374 | self.couchdb.login("steve", password: "password") { response in
375 | switch response {
376 | case .error(let error):
377 | XCTAssertNil(error)
378 | case .success(let response, let success):
379 | XCTAssertEqual(response.response?.statusCode, 200)
380 | XCTAssert(success.ok!)
381 | }
382 |
383 | // delete user
384 | let database = self.couchdb.use("_users")
385 | database.get("org.couchdb.user:steve") { response in
386 | switch response {
387 | case .error(let error):
388 | XCTAssertNil(error)
389 | case .success(let response, let json):
390 | XCTAssertEqual(response.response?.statusCode, 200)
391 | let doc = CouchDB.Document(data: json as! [String : Any])
392 |
393 | database.delete(doc) { _ in
394 | expectation.fulfill()
395 | }
396 | }
397 | }
398 | }
399 |
400 | }
401 |
402 | waitForExpectations(timeout: timeout, handler: nil)
403 | }
404 |
405 |
406 |
407 | func testGetSession() {
408 | let expectation = self.expectation(description: "get session")
409 |
410 | // create user
411 | let wiff = CouchDB.User(name: "wiff", password: "pwd", roles: ["dog"])
412 | couchdb.createUser(wiff) { _ in
413 |
414 | // login
415 | self.couchdb.login("wiff", password: "pwd") { _ in
416 |
417 | // get session
418 | self.couchdb.getSession() { response in
419 |
420 | switch response {
421 | case .error(let error):
422 | XCTAssertNil(error)
423 | case .success(let response, let res):
424 | XCTAssertEqual(response.response?.statusCode, 200)
425 | XCTAssertEqual(res.info.authenticated, "cookie")
426 | XCTAssertEqual(res.userCtx.roles, ["dog"])
427 | XCTAssert(res.ok!)
428 | }
429 |
430 | // delete user
431 | let database = self.couchdb.use("_users")
432 | database.get("org.couchdb.user:wiff") { response in
433 | switch response {
434 | case .error(let error):
435 | XCTAssertNil(error)
436 | case .success(let response, let json):
437 | XCTAssertEqual(response.response?.statusCode, 200)
438 | let doc = CouchDB.Document(data: json as! [String : Any])
439 |
440 | database.delete(doc) { _ in
441 | expectation.fulfill()
442 | }
443 | }
444 | }
445 |
446 | }
447 |
448 | }
449 |
450 | }
451 |
452 | waitForExpectations(timeout: timeout, handler: nil)
453 | }
454 |
455 |
456 |
457 | func testLogout() {
458 | let expectation = self.expectation(description: "logout")
459 |
460 | // create user
461 | let nitika = CouchDB.User(name: "nitika", password: "pwd", roles: ["dog"])
462 | couchdb.createUser(nitika) { _ in
463 |
464 | // login
465 | self.couchdb.login("nitika", password: "pwd") { _ in
466 |
467 | // make sure user has session
468 | self.couchdb.getSession() { session in
469 | switch session {
470 | case .error(let error):
471 | XCTAssertNil(error)
472 | case .success(let response, let success):
473 | XCTAssertEqual(response.response?.statusCode, 200)
474 | XCTAssert(success.ok!)
475 | }
476 |
477 | // logout
478 | self.couchdb.logout() { response in
479 | switch response {
480 | case .error(let error):
481 | XCTAssertNil(error)
482 | case .success(let response, let res):
483 | XCTAssertEqual(response.response?.statusCode, 200)
484 | XCTAssert(res.ok!)
485 | }
486 |
487 | // delete user
488 | let database = self.couchdb.use("_users")
489 | database.get("org.couchdb.user:nitika") { response in
490 | switch response {
491 | case .error(let error):
492 | XCTAssertNil(error)
493 | case .success(let response, let json):
494 | XCTAssertEqual(response.response?.statusCode, 200)
495 | let doc = CouchDB.Document(data: json as! [String : Any])
496 |
497 | database.delete(doc) { _ in
498 | expectation.fulfill()
499 | }
500 | }
501 | }
502 |
503 | }
504 | }
505 |
506 |
507 | }
508 |
509 | }
510 |
511 | waitForExpectations(timeout: timeout, handler: nil)
512 | }
513 |
514 | func testCookie() {
515 | let expectation = self.expectation(description: "cookie")
516 |
517 | // create user
518 | let juna = CouchDB.User(name: "juna", password: "juna", roles: ["user"])
519 | couchdb.createUser(juna) { _ in
520 |
521 | // login to get cookie
522 | self.couchdb.login("juna", password: "juna") { response in
523 | switch response {
524 | case .error(let error):
525 | XCTAssertNil(error)
526 | case .success(let response, let success):
527 | XCTAssertEqual(response.response?.statusCode, 200)
528 | XCTAssert(success.ok!)
529 |
530 | // get cookie from response
531 | if
532 | let headerFields = response.response?.allHeaderFields as? [String: String],
533 | let uri = response.request?.url {
534 | let cookies = HTTPCookie.cookies(withResponseHeaderFields: headerFields, for: uri)
535 | let cookie = cookies[0]
536 |
537 | // create another couchdb instance without password but with cookie
538 | // auth headers are empty and therefore only cookie is used for auth
539 | let couchdb2 = CouchDB(url: url, cookie: cookie)
540 | couchdb2.getSession() { response in
541 |
542 | switch response {
543 | case .error(let error):
544 | XCTAssertNil(error)
545 | case .success(let response, let res):
546 | XCTAssertEqual(response.response?.statusCode, 200)
547 | XCTAssertEqual(res.info.authenticated, "cookie")
548 | XCTAssertEqual(res.userCtx.roles, ["user"])
549 | XCTAssert(res.ok!)
550 | XCTAssertEqual(res.userCtx.name, "juna")
551 | }
552 |
553 | // delete user
554 | let database = self.couchdb.use("_users")
555 | database.get("org.couchdb.user:juna") { response in
556 | switch response {
557 | case .error(let error):
558 | XCTAssertNil(error)
559 | case .success(let response, let json):
560 | XCTAssertEqual(response.response?.statusCode, 200)
561 | let doc = CouchDB.Document(data: json as! [String : Any])
562 |
563 | database.delete(doc) { _ in
564 | expectation.fulfill()
565 | }
566 | }
567 | }
568 | }
569 | }
570 | }
571 | }
572 |
573 | }
574 | waitForExpectations(timeout: timeout, handler: nil)
575 | }
576 |
577 |
578 |
579 | }
580 |
--------------------------------------------------------------------------------