Skip to content

Commit 2b361b7

Browse files
makonigevartoskyCopilot
authored
2.2.0 (#35)
* 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. * updated dependencies * Docs updated * Delete .github/workflows/CodeQL.yml * dependencies updated * fixed when update method didn’t use passed dateEncodingStrategy * noData error added * migrating to new HTTPClientRequest from HTTPClient.Request wip * migrating to new HTTPClientRequest from HTTPClient.Request wip * migrating to new HTTPClientRequest from HTTPClient.Request wip * migrating to new HTTPClientRequest from HTTPClient.Request wip * migrating to new HTTPClientRequest from HTTPClient.Request wip * migrating to new HTTPClientRequest from HTTPClient.Request wip * … * migrating to new HTTPClientRequest from HTTPClient.Request wip * rename * tests updated * auth fixed * collect body bytes before returning response * param renamed to make keep backward compatibility with old methods * marking old find as deprecated * private * deprecated message * renames * moved deprecations * docs * docs * added Codable to CouchDBRepresentable protocol * added RowsResponse model * docs * Vapor tutorial updated * docs * docs and refactoring * docs and refactoring * Tutorials updated * docs * platforms list updated * minimum swift version 5.8 * workflow updated * Update build-ubuntu.yml * Update build-macos.yml * import NIOFoundationCompat to fix building on Ubuntu * using async-http-client from 1.21.0. Not calling http * Using HTTPClient.shared if eventLoopGroup not provided. No more calls httpClient.syncShutdown() if using shared singleton * docs updated * docs updated * Vapor tutorial updated * A SwiftUI tutorial * tutorial fixed * updated dependencies * Package.resolved * docs updated * userName param is now required for CouchDB init * cleanup * docs * docs * docs * docs * docs * docs * docs * docs * docs * docs * docs * docs * docs * docs * docs * docs * dependencices updated * updated swift-docc-plugin URL. Updated dependencies to latest versions. * Update build-ubuntu.yml * dependencies updated * deleted deprecated methods * Sendable conformance * swift-format added * formatting * formatting * revert sendable * updated dependencies * Sensable conformance * updated CouchDBRepresentable protocol * Sendable conformance * Strict concurrency implemented * Swift 6 * docs updated * errors and docs * docs * docs * docs wip * docs * wip * wip * docs * docs * get only _rev * tutorials updated * docs * Update README.md * Update README.md * updated GitHub actions configs * dependencies updated * updated docs * code formatting * refactoring * localized error messages * Added error messages translations * More translations * fixes for Linux * docs * create HTTPClient if not provided in init * new test added * use FoundationEssentials if possible * tests updated * dependencies updated * added shutdown method * formatting * added tutorial for Hummingbird * tutorials * tutorial * tutorials * docs * renamed couchdb-vapor to couchdb-swift * docs * try to use FoundationEssentials everywhere and Dispatch * removed FoundationEssentials usage, can’t use Bundle with it * dependencies updated * dependencies * dependencies updated * added new conflictError error * handle conflict error in Update method * Added missing authorization for delete document request * tabs * tabs * added handling of not found error in update method * added handling of not found error in delete method * added more tests * translations for CONFLICT_ERROR * fixed date format * Percent-encode username and password * updated config * updated actions configs * notFound error added * Throw .notFound error for get requests * translations * HTTPClientTests added using Swift Testing * migrated to Swift Testing * tabs * Mango Query implementation * more tests * tests updated * wip * wip * tests updated * more tests and fixes * docs * new tutorial * New tutorial * wip * wip * tutorials updated * test updated * Attachments API * formatting * readme * … * … * fixes * updated workflows * Update Sources/CouchDBClient/CouchDBClient.docc/Tutorials/AdvancedMangoQueries/AdvancedMangoQueries-5.swift Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * correct init * updated tests * tests updated * MangoSortField struct * readme * docs * throw error * Rename --------- Co-authored-by: Gregório Gevartosky Torrezan <greg.gevartosky@gmail.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 31a7e58 commit 2b361b7

23 files changed

+1483
-86
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: ["6.0", "6.0.3", "6.1"]
14+
swift: ["6.0", "6.1"]
1515
runs-on: ubuntu-latest
1616
container:
1717
image: swift:${{ matrix.swift }}

.github/workflows/test-ubuntu.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
strategy:
1313
fail-fast: false
1414
matrix:
15-
couchdb: [latest, "3.4", "3.3", "3.2"]
15+
couchdb: [latest, "3.4"]
1616
runs-on: ubuntu-latest
1717
services:
1818
swift:

README.md

Lines changed: 72 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,51 @@
11
# CouchDB Client for Swift
22

33
<p align="center">
4-
<a href="/makoni/couchdb-swift">
4+
<a href="/makoni/couchdb-swift">
55
<img src="https://spaceinbox.me/images/appicons/5cff134d1bb4a2e90faea5cf4e0002a2.svg?31-a992eba6ad7e189f4b3e0988936056ca" height="200">
66
</a>
77
</p>
88

99
[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fmakoni%2Fcouchdb-swift%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/makoni/couchdb-swift)
1010
[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fmakoni%2Fcouchdb-swift%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/makoni/couchdb-swift)
11-
[![Vapor 4](https://img.shields.io/badge/vapor-4-blue.svg?style=flat)](https://vapor.codes)
1211

1312
[![Build on macOS](https://github.com/makoni/couchdb-swift/actions/workflows/build-macos.yml/badge.svg?branch=master)](https://github.com/makoni/couchdb-swift/actions/workflows/build-macos.yml)
1413
[![Build on Ubuntu](https://github.com/makoni/couchdb-swift/actions/workflows/build-ubuntu.yml/badge.svg?branch=master)](https://github.com/makoni/couchdb-swift/actions/workflows/build-ubuntu.yml)
1514
[![Test on Ubuntu](https://github.com/makoni/couchdb-swift/actions/workflows/test-ubuntu.yml/badge.svg?branch=master)](https://github.com/makoni/couchdb-swift/actions/workflows/test-ubuntu.yml)
1615

1716

18-
1917
This is a simple library to work with CouchDB in Swift.
2018

21-
- The latest version supports strict concurrency: `CouchDBClient` is an actor and requires Swift 6.0 or newer. For Swift 5, you can still use version `1.7.0`.
22-
- Compatible with Vapor 4.
23-
- Version `1.0.0` can be used with Vapor 4 without `async/await`; Swift 5.3 is required.
24-
- You can use the old version for Vapor 3 by checking out the `vapor3` branch or using versions earlier than `1.0.0`.
19+
---
2520

26-
The only dependency for this library is [`async-http-client`](https://github.com/swift-server/async-http-client).
21+
## Features
2722

28-
---
23+
- Strict concurrency: `CouchDBClient` is an actor (Swift 6+)
24+
- Attachments API: upload, download, delete files/images
25+
- Mango queries and indexes
26+
- Document CRUD (create, read, update, delete)
27+
- Vapor and Hummingbird integration
28+
- Robust error handling
29+
30+
## Supported Platforms & Swift Versions
31+
32+
- Swift 6.0+ (actor-based concurrency)
33+
- Swift 5.x (use version 1.7.0)
34+
- macOS, Linux (tested on Ubuntu)
35+
- Compatible with Vapor 4 and Hummingbird
36+
37+
## Testing
38+
39+
Comprehensive test suite covers all major APIs, including Attachments. Run tests with:
40+
41+
```bash
42+
COUCHDB_PASS=myPassword swift test
43+
```
2944

3045
## Documentation
3146

3247
Find documentation, examples, and tutorials [here](https://spaceinbox.me/docs/couchdbclient/documentation/couchdbclient).
3348

34-
---
35-
3649
## Installation
3750

3851
### Swift Package Manager
@@ -45,8 +58,6 @@ dependencies: [
4558
]
4659
```
4760

48-
---
49-
5061
## Initialization
5162

5263
```swift
@@ -80,6 +91,43 @@ let couchDBClient = CouchDBClient(config: config)
8091

8192
## Usage examples
8293

94+
### Uploading an Attachment
95+
96+
```swift
97+
let response = try await couchDBClient.uploadAttachment(
98+
dbName: "myDatabase",
99+
docId: "docid",
100+
attachmentName: "image.png",
101+
data: imageData,
102+
contentType: "image/png",
103+
rev: "currentRev"
104+
)
105+
print("Attachment uploaded, new revision: \(response.rev)")
106+
```
107+
108+
### Downloading an Attachment
109+
110+
```swift
111+
let attachmentData = try await couchDBClient.downloadAttachment(
112+
dbName: "myDatabase",
113+
docId: "docid",
114+
attachmentName: "image.png"
115+
)
116+
print("Downloaded attachment, size: \(attachmentData.count) bytes")
117+
```
118+
119+
### Deleting an Attachment
120+
121+
```swift
122+
let deleteResponse = try await couchDBClient.deleteAttachment(
123+
dbName: "myDatabase",
124+
docId: "docid",
125+
attachmentName: "image.png",
126+
rev: "currentRev"
127+
)
128+
print("Attachment deleted, new revision: \(deleteResponse.rev)")
129+
```
130+
83131
### Define Your Document Model
84132

85133
```swift
@@ -144,11 +192,20 @@ print(dbs)
144192

145193
### Find Documents in a Database by Selector
146194
```swift
147-
let selector = ["selector": ["name": "Sam"]]
148-
let docs: [ExpectedDoc] = try await couchDBClient.find(in: "databaseName", selector: selector)
195+
let selector: [String: MangoValue] = [
196+
"type": .string("user"),
197+
"age": .comparison(.greaterThan(.int(30)))
198+
]
199+
let query = MangoQuery(selector: selector, fields: ["name", "email"], sort: [MangoSortField(field: "name", direction: .asc)], limit: 10, skip: 0)
200+
let docs: [ExpectedDoc] = try await couchDBClient.find(inDB: "databaseName", query: query)
149201
print(docs)
150202
```
151203

152204
### Using with Vapor
153205
Here's a simple [tutorial](https://spaceinbox.me/docs/couchdbclient/tutorials/couchdbclient/vaportutorial) for Vapor.
154206

207+
---
208+
209+
## License
210+
211+
This project is licensed under the MIT License. See [LICENSE](LICENSE) for details.

Sources/CouchDBClient/CouchDBClient.docc/CouchDBClient.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ Built on top of [AsyncHTTPClient](https://github.com/swift-server/async-http-cli
3131
- **Document Operations**:
3232
- Get a document by ID or retrieve documents using a view.
3333
- Insert or update documents.
34-
- Find documents using a selector.
34+
- Find documents using a MangoQuery and type-safe selectors (see MangoValue and MangoComparison).
3535
- Delete documents.
3636

3737
- **Authorization**:
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Advanced Mango Queries Step 1: Building Selectors
2+
struct User: Codable {
3+
let name: String
4+
let email: String
5+
}
6+
7+
Task {
8+
let query = MangoQuery(
9+
selector: [
10+
"type": .string("user"),
11+
"age": .comparison(.greaterThan(.int(30)))
12+
]
13+
)
14+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Advanced Mango Queries Step 2: Sorting, Limit, and Skip
2+
struct User: Codable {
3+
let name: String
4+
let email: String
5+
}
6+
7+
Task {
8+
let query = MangoQuery(
9+
selector: [
10+
"type": .string("user"),
11+
"age": .comparison(.greaterThan(.int(30)))
12+
],
13+
sort: [MangoSortField(field: "name", direction: .asc)],
14+
limit: 10,
15+
skip: 0
16+
)
17+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Advanced Mango Queries Step 3: Projections (Fields)
2+
struct User: Codable {
3+
let name: String
4+
let email: String
5+
}
6+
7+
Task {
8+
let query = MangoQuery(
9+
selector: [
10+
"type": .string("user"),
11+
"age": .comparison(.greaterThan(.int(30)))
12+
],
13+
sort: [MangoSortField(field: "name", direction: .asc)],
14+
limit: 10,
15+
skip: 0,
16+
fields: ["name", "email"]
17+
)
18+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Advanced Mango Queries Step 4: Index Usage
2+
struct User: Codable {
3+
let name: String
4+
let email: String
5+
}
6+
7+
Task {
8+
let query = MangoQuery(
9+
selector: [
10+
"type": .string("user"),
11+
"age": .comparison(.greaterThan(.int(30)))
12+
],
13+
sort: [MangoSortField(field: "name", direction: .asc)],
14+
limit: 10,
15+
skip: 0,
16+
fields: ["name", "email"],
17+
useIndex: "my-index"
18+
)
19+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Advanced Mango Queries Step 5: Executing the Query
2+
struct User: Codable {
3+
let name: String
4+
let email: String
5+
}
6+
7+
Task {
8+
let query = MangoQuery(
9+
selector: [
10+
"type": .string("user"),
11+
"age": .comparison(.greaterThan(.int(30)))
12+
],
13+
sort: [MangoSortField(field: "name", direction: .asc)],
14+
limit: 10,
15+
skip: 0,
16+
fields: ["name", "email"],
17+
useIndex: "my-index"
18+
)
19+
20+
let result: CouchDBFindResponse<User> = try await couchDBClient.find(inDB: dbName, query: query)
21+
print(result.docs)
22+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
@Tutorial(time: 5) {
2+
@Intro(title: "Advanced Mango Queries") {
3+
Learn how to build complex selectors, use sorting, pagination, projections, and optimize queries with indexes in CouchDB.
4+
5+
@Image(source: logo.svg, alt: "Advanced Mango Queries illustration")
6+
}
7+
8+
@Section(title: "Building Selectors and Queries") {
9+
@ContentAndMedia {
10+
Advanced Mango queries allow you to filter, sort, and project CouchDB documents using expressive selectors and indexes. The following steps will guide you through building selectors, adding sort/limit/skip, using fields for projections, and optimizing queries with indexes.
11+
}
12+
13+
@Steps {
14+
@Step {
15+
Use nested dictionaries and operators for selectors ([CouchDB Mango Query Docs](https://docs.couchdb.org/en/stable/api/database/find.html)).
16+
@Code(name: "main.swift", file: AdvancedMangoQueries-1.swift)
17+
}
18+
19+
@Step {
20+
Add sort, limit, and skip for pagination.
21+
@Code(name: "main.swift", file: AdvancedMangoQueries-2.swift)
22+
}
23+
24+
@Step {
25+
Use fields for projections.
26+
@Code(name: "main.swift", file: AdvancedMangoQueries-3.swift)
27+
}
28+
29+
@Step {
30+
Create indexes for query optimization.
31+
@Code(name: "main.swift", file: AdvancedMangoQueries-4.swift)
32+
}
33+
34+
@Step {
35+
Execute the Mango query using CouchDBClient's `find` method to retrieve results from the database.
36+
@Code(name: "main.swift", file: AdvancedMangoQueries-5.swift)
37+
}
38+
}
39+
}
40+
}

0 commit comments

Comments
 (0)