This is a simple library to work with CouchDB in Swift.
- Strict concurrency:
CouchDBClient
is an actor (Swift 6+) - Attachments API: upload, download, delete files/images
- Mango queries and indexes
- Document CRUD (create, read, update, delete)
- Vapor and Hummingbird integration
- Robust error handling
- Swift 6.0+ (actor-based concurrency)
- Swift 5.x (use version 1.7.0)
- macOS, Linux (tested on Ubuntu)
- Compatible with Vapor 4 and Hummingbird
Comprehensive test suite covers all major APIs, including Attachments. Run tests with:
COUCHDB_PASS=myPassword swift test
Find documentation, examples, and tutorials here.
Add the following to the dependencies
section of your Package.swift
:
dependencies: [
.package(url: "https://github.com/makoni/couchdb-swift.git", from: "2.1.0"),
]
let config = CouchDBClient.Config(
couchProtocol: .http,
couchHost: "127.0.0.1",
couchPort: 5984,
userName: "admin",
userPassword: "",
requestsTimeout: 30
)
let couchDBClient = CouchDBClient(config: config)
To avoid hardcoding your password, you can pass the COUCHDB_PASS parameter via the command line. For example, you can run your server-side Swift project as follows:
COUCHDB_PASS=myPassword /path/.build/x86_64-unknown-linux-gnu/release/Run
In this case, use the initializer without the userPassword parameter:
let config = CouchDBClient.Config(
couchProtocol: .http,
couchHost: "127.0.0.1",
couchPort: 5984,
userName: "admin",
requestsTimeout: 30
)
let couchDBClient = CouchDBClient(config: config)
let response = try await couchDBClient.uploadAttachment(
dbName: "myDatabase",
docId: "docid",
attachmentName: "image.png",
data: imageData,
contentType: "image/png",
rev: "currentRev"
)
print("Attachment uploaded, new revision: \(response.rev)")
let attachmentData = try await couchDBClient.downloadAttachment(
dbName: "myDatabase",
docId: "docid",
attachmentName: "image.png"
)
print("Downloaded attachment, size: \(attachmentData.count) bytes")
let deleteResponse = try await couchDBClient.deleteAttachment(
dbName: "myDatabase",
docId: "docid",
attachmentName: "image.png",
rev: "currentRev"
)
print("Attachment deleted, new revision: \(deleteResponse.rev)")
// Example struct
struct ExpectedDoc: CouchDBRepresentable {
var name: String
var _id: String = NSUUID().uuidString
var _rev: String?
func updateRevision(_ newRevision: String) -> Self {
return ExpectedDoc(name: name, _id: _id, _rev: newRevision)
}
}
var testDoc = ExpectedDoc(name: "My name")
testDoc = try await couchDBClient.insert(
dbName: "databaseName",
doc: testDoc
)
print(testDoc) // testDoc has _id and _rev values now
// get data from a database by document ID
var doc: ExpectedDoc = try await couchDBClient.get(fromDB: "databaseName", uri: "documentId")
print(doc)
// Update value
doc.name = "Updated name"
doc = try await couchDBClient.update(
dbName: testsDB,
doc: doc
)
print(doc) // doc will have updated name and _rev values now
let response = try await couchDBClient.delete(fromDb: "databaseName", doc: doc)
// or by uri
let response = try await couchDBClient.delete(fromDb: "databaseName", uri: doc._id,rev: doc._rev)
let dbs = try await couchDBClient.getAllDBs()
print(dbs)
// prints: ["_global_changes", "_replicator", "_users", "yourDBname"]
let selector: [String: MangoValue] = [
"type": .string("user"),
"age": .comparison(.greaterThan(.int(30)))
]
let query = MangoQuery(selector: selector, fields: ["name", "email"], sort: [MangoSortField(field: "name", direction: .asc)], limit: 10, skip: 0)
let docs: [ExpectedDoc] = try await couchDBClient.find(inDB: "databaseName", query: query)
print(docs)
Here's a simple tutorial for Vapor.
This project is licensed under the MIT License. See LICENSE for details.