Skip to content

Commit 8e0707c

Browse files
makonigevartosky
andauthored
1.3.0 (#14)
* swift-docc-plugin 1.3.0 * async-http-client 1.19.0 * replaced deprecated .createNew with the new .singleton * Adding _find capability. (#13) * docs * tabs * renames * added test for find method with body * docs added * findError added * tests renamed * added test for find method with generic type * docs * README updated * updated dependencies * docs updated * try Swift 5.7.1 * Update build-ubuntu.yml * Swift 5.7.3 * Revert "Swift 5.7.3" This reverts commit ab8f67a. --------- Co-authored-by: Gregório Gevartosky Torrezan <[email protected]>
1 parent 42da8ad commit 8e0707c

File tree

9 files changed

+221
-23
lines changed

9 files changed

+221
-23
lines changed

.github/workflows/build-ubuntu.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ jobs:
1111
name: Build on Ubuntu with Swift ${{matrix.swift}}
1212
strategy:
1313
matrix:
14-
swift: [5.8.1, 5.7.3, 5.6.3]
14+
swift: [5.9, 5.8.1, 5.7.3]
1515
runs-on: ubuntu-latest
1616
container:
1717
image: swift:${{matrix.swift}}

Package.resolved

Lines changed: 41 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// swift-tools-version:5.6
1+
// swift-tools-version:5.7.1
22
// The swift-tools-version declares the minimum version of Swift required to build this package.
33

44
import PackageDescription

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,13 @@ print(dbs)
129129
// prints: ["_global_changes", "_replicator", "_users", "yourDBname"]
130130
```
131131

132+
Find documents in DB by selector:
133+
```swift
134+
let selector = ["selector": ["name": "Sam"]]
135+
let docs: [ExpectedDoc] = try await couchDBClient.find(in: "databaseName", selector: selector)
136+
print(docs)
137+
```
138+
132139
### Using with Vapor
133140
Here's a simple [tutorial](https://spaceinbox.me/docs/couchdbclient/tutorials/couchdbclient/vaportutorial) for Vapor.
134141

Sources/CouchDBClient/CouchDBClient.docc/CouchDBClient.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Currently CouchDBClient supports:
1717
- Get databases list.
1818
- Get document by id or documents using view.
1919
- Insert/update documents.
20+
- Find documents by selector.
2021
- Delete documents.
2122
- CouchDB authorization.
2223

Sources/CouchDBClient/CouchDBClient.docc/Extensions/Client.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,7 @@ A CouchDB client class with methods using Swift Concurrency.
2727
- ``insert(dbName:doc:dateEncodingStrategy:eventLoopGroup:)``
2828
- ``update(dbName:doc:dateEncodingStrategy:eventLoopGroup:)``
2929
- ``update(dbName:uri:body:eventLoopGroup:)``
30+
- ``find(in:body:eventLoopGroup:)``
31+
- ``find(in:selector:dateDecodingStrategy:eventLoopGroup:)``
3032
- ``delete(fromDb:doc:eventLoopGroup:)``
3133
- ``delete(fromDb:uri:rev:eventLoopGroup:)``

Sources/CouchDBClient/CouchDBClient.swift

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ public enum CouchDBClientError: Error {
2222
case insertError(error: CouchDBError)
2323
/// Update request wasn't successful.
2424
case updateError(error: CouchDBError)
25+
/// Find request wasn't successful.
26+
case findError(error: CouchDBError)
2527
/// Uknown response from CouchDB.
2628
case unknownResponse
2729
/// Wrong username or password.
@@ -41,6 +43,8 @@ extension CouchDBClientError: LocalizedError {
4143
return "Insert request wasn't successful: \(error.localizedDescription)"
4244
case .updateError(let error):
4345
return "Update request wasn't successful: \(error.localizedDescription)"
46+
case .findError(let error):
47+
return "Find request wasn't successful: \(error.localizedDescription)"
4448
case .unknownResponse:
4549
return "Uknown response from CouchDB."
4650
case .unauthorized:
@@ -478,6 +482,96 @@ public class CouchDBClient {
478482
throw parsingError
479483
}
480484
}
485+
486+
/// Find data in DB by selector.
487+
///
488+
/// Example:
489+
///
490+
/// ```swift
491+
/// // find documents in DB by selector
492+
/// let selector = ["selector": ["name": "Sam"]]
493+
/// let docs: [ExpectedDoc] = try await couchDBClient.find(in: testsDB, selector: selector)
494+
/// ```
495+
///
496+
/// - Parameters:
497+
/// - in dbName: DB name.
498+
/// - selector: Codable representation of json selector query.
499+
/// - eventLoopGroup: NIO's EventLoopGroup object. New will be created if nil value provided.
500+
/// - Returns: Array of documents [T].
501+
public func find<T: Codable & CouchDBRepresentable>(in dbName: String, selector: Codable, dateDecodingStrategy: JSONDecoder.DateDecodingStrategy = .secondsSince1970, eventLoopGroup: EventLoopGroup? = nil) async throws -> [T] {
502+
let encoder = JSONEncoder()
503+
let selectorData = try encoder.encode(selector)
504+
505+
let findResponse = try await find(
506+
in: dbName,
507+
body: .data(selectorData),
508+
eventLoopGroup: eventLoopGroup
509+
)
510+
511+
guard var body = findResponse.body, let bytes = body.readBytes(length: body.readableBytes) else {
512+
throw CouchDBClientError.unknownResponse
513+
}
514+
515+
let data = Data(bytes)
516+
let decoder = JSONDecoder()
517+
decoder.dateDecodingStrategy = dateDecodingStrategy
518+
519+
do {
520+
let doc = try decoder.decode(CouchDBFindResponse<T>.self, from: data)
521+
return doc.docs
522+
} catch let parsingError {
523+
if let couchdbError = try? decoder.decode(CouchDBError.self, from: data) {
524+
throw CouchDBClientError.findError(error: couchdbError)
525+
}
526+
throw parsingError
527+
}
528+
}
529+
530+
/// Find data in DB by selector.
531+
///
532+
/// Example:
533+
/// ```swift
534+
/// let selector = ["selector": ["name": "Greg"]]
535+
/// let bodyData = try JSONEncoder().encode(selector)
536+
/// var findResponse = try await couchDBClient.find(in: testsDB, body: .data(bodyData))
537+
///
538+
/// let bytes = findResponse.body!.readBytes(length: findResponse.body!.readableBytes)!
539+
/// let docs = try JSONDecoder().decode(CouchDBFindResponse<ExpectedDoc>.self, from: Data(bytes)).docs
540+
/// ```
541+
/// - Parameters:
542+
/// - dbName: DB name.
543+
/// - body: Request body data.
544+
/// - eventLoopGroup: NIO's EventLoopGroup object. New will be created if nil value provided.
545+
/// - Returns: Request response.
546+
public func find(in dbName: String, body: HTTPClient.Body, eventLoopGroup: EventLoopGroup? = nil) async throws -> HTTPClient.Response {
547+
try await authIfNeed(eventLoopGroup: eventLoopGroup)
548+
549+
let httpClient: HTTPClient
550+
if let eventLoopGroup = eventLoopGroup {
551+
httpClient = HTTPClient(eventLoopGroupProvider: .shared(eventLoopGroup))
552+
} else {
553+
httpClient = HTTPClient(eventLoopGroupProvider: .singleton)
554+
}
555+
556+
defer {
557+
DispatchQueue.main.async {
558+
try? httpClient.syncShutdown()
559+
}
560+
}
561+
562+
let url = buildUrl(path: "/" + dbName + "/_find", query: [])
563+
var request = try buildRequest(fromUrl: url, withMethod: .POST)
564+
request.body = body
565+
let response = try await httpClient
566+
.execute(request: request, deadline: .now() + .seconds(requestsTimeout))
567+
.get()
568+
569+
if response.status == .unauthorized {
570+
throw CouchDBClientError.unauthorized
571+
}
572+
573+
return response
574+
}
481575

482576
/// Update data in DB.
483577
///
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//
2+
// CouchDBFindResponse.swift
3+
//
4+
//
5+
// Created by Gregorio Gevartosky Torrezan on 2023-11-15.
6+
//
7+
8+
import Foundation
9+
10+
public struct CouchDBFindResponse<T: Codable & CouchDBRepresentable>: Codable {
11+
var docs: [T]
12+
var bookmark: String?
13+
}

0 commit comments

Comments
 (0)