CouchDB library with a simple, functional-programing-friendly API.
Forked from Cot, and renamed blue-cot
in reference to the Bluebird promises it was returning until v4.0.0
.
Summary
Installing
npm install blue-cot
Specificities of this lib
Especially compared to Cot from which it is forked
- Class-less, thus a different initialization, but the rest of the API stays the same
- Consequently,
blue-cot
is this
-free: no need to bind functions contexts! 4xx
and 5xx
responses will return rejected promises (should be handled with .catch
)- Adds a few new functions, notably some view functions goodies
- Uses Cookie Authentication instead of Basic Auth for better performance
- Uses a single persistent connexion to CouchDB by default
Initialization
const bluecot = require('blue-cot')
const config = {
protocol: 'http',
hostname: 'localhost',
port: 5984,
username: 'your-couchdb-username'
password: 'your-couchdb-password'
debug: true,
agent: myAgent
}
const getDbApi = bluecot(config)
const db = getDbApi('some-db-name')
with Bluebird
From v4.0.0
, blue-cot
stopped returning Bluebird promises, but if you miss that feature, you can recover it by initializing bluebird
before blue-cot
:
global.Promise = require('bluebird')
const bluecot = require('blue-cot')
const getDbApi = bluecot(config)
const db = getDbApi('some-db-name')
API
Database functions
To handle database and design documents creation, see couch-init2
info
GET /<dbName>
const data = await db.info()
Documents functions
get
GET /<dbName>/<docId>
Takes a document id and optionaly a rev id to get a specific version:
const latestDocVersion = await db.get('doc-1')
const specificVersion = await db.get('doc-1', '2-b8476e8877ff5707de9e62e70a8e0aeb')
Missing documents are treated as an error, and thus return a rejected promise.
post
POST /<dbName>
const res = await db.post(doc)
Creates a new document or updates an existing document. If doc._id
is undefined, CouchDB will generate a new ID for you.
On 201, returns result from CouchDB which looks like: {"ok":true, "id":"<docId>", "rev":"<docRev>"}
All other status codes (including 409, conflict) are treated as errors, and thus return a rejected promise.
put
PUT /<dbName>/<doc._id>
const res = await db.put(doc)
On 409 (conflict) returns result from CouchDB which looks like: {"error":"conflict"}
On 201, returns result from CouchDB which looks like: {"ok":true, "id":"<docId>", "rev":"<docRev>"}
All other status codes are treated as errors, and thus return a rejected promise.
delete
DELETE /<dbName>/<docId>?rev=<rev>
const res = await db.delete(docId, rev)
On 200, returns result from CouchDB which looks like: {"ok":true, "id":"<docId>", "rev":"<docRev>"}
All other status codes are treated as errors, and thus return a rejected promise.
If you wish to gracefully handle update conflicts while deleting, use db.put()
on a document with _deleted
set to true
:
doc._deleted = true
const res = await db.put(doc)
if (!res.ok) {
}
exists
GET /<dbName>/<docId>
const res = await db.exists(docId)
Returns a promise resolving to true if it exist, or a rejected promise if it doesn't.
batch
POST /<dbName>?batch=ok
const res = await db.batch(doc)
doc: Batch Mode
Creates or updates a document but doesn't wait for success. Conflicts will not be detected.
On 202, returns result from CouchDB which looks like: {"ok":true, "id":"<docId>"}
The rev isn't returned because CouchDB returns before checking for conflicts. If there is a conflict, the update will be silently lost.
All other status codes are treated as errors, and thus return a rejected promise.
update
const res = await db.update(docId, updateFunction)
Gets the specified document, passes it to updateFunction
, and then saves the results of updateFunction
over the document
The process loops if there is an update conflict.
If updateFunction
needs to do asynchronous work, it may return a promise.
bulk
POST /<dbName>/_bulk_docs
const res = await db.bulk(docs)
See CouchDB documentation for more information
allDocs
GET /<dbName>/_all_docs?<properly encoded query>
const { rows } = await db.allDocs(query)
Queries the _all_docs
view. query
supports the same keys as in db.view
.
allDocsKeys
Loads documents with the specified keys and query parameters
const { rows } = await db.allDocsKeys(keys, query)
Couchdb documentation
fetch
Takes doc ids, returns docs.
const { docs, errors } = await db.fetch([ 'doc-1', 'doc-2', 'doc-3', 'some-non-existing-doc' ])
docs[0]._id === 'doc-1'
docs[1]._id === 'doc-2'
docs[2]._id === 'doc-3'
errors[0].key === 'some-non-existing-doc'
errors[0].error === 'not_found'
changes
Queries the changes feed given the specified query. query
may contain the following keys:
filter
: filter function to useinclude_docs
: if true, results will contain entire documentlimit
: the maximum number of change rows this query should returnsince
: results will start immediately after the sequence number provided herelongpoll
: if true, query will send feed=longpolltimeout
: timeout in milliseconds for logpoll queries
See CouchDB changes feed documentation
listRevs
Takes a doc id, returns the doc's rev infos
const revsInfo = await db.listRevs('doc-1')
revsInfo
will look something like:
[
{ rev: '3-6a8869bc7fff815987ff9b7fda3e10e3', status: 'available' },
{ rev: '2-88476e8877ff5707de9e62e70a8e0aeb', status: 'available' },
{ rev: '1-a8bdf0ef0b7049d35c781210723b9ff9', status: 'available' }
]
revertLastChange
Takes a doc id and reverts its last change, recovering the previous version.
Only works if there is a previous version and if it is still available in the database (that is, if it wasn't deleted by a database compaction).
It doesn't delete the last version, it simply creates a new version that is exactly like the version before the current one.
const res = await db.revertLastChange('doc-1')
revertToLastVersionWhere
Takes a doc id and a function, and reverts to the last version returning a truthy result when passed through this function.
Same warnings apply as for revertLastChange
.
const desiredVersionTestFunction = doc => doc.foo === 2
db.revertToLastVersionWhere('doc-1', desiredVersionTestFunction)
undelete
Mistakes happen
await db.delete(docId, docRev)
await db.undelete(docId))
const restoredDoc = await db.get(docId))
:warning: this will obviously not work if the version before deletion isn't in the database (because the database was compressed or it's a freshly replicated database), or if the database was purged from deleted documents.
View functions
view
GET /<dbName>/_desgin/<designName>/_view/<viewName>?<properly encoded query>
const { rows, total_rows, offset } = db.view(designName, viewName, query)
Queries a view with the given name in the given design doc. query
should be an object with any of the following keys:
- descending
- endkey
- endkey_docid
- group
- group_level
- include_docs
- inclusive_end
- key
- limit
- reduce
- skip
- stale
- startkey
- startkey_docid
- update_seq
For more information, refer to Couchdb documentation
viewQuery
viewKeysQuery
viewKeys
Design doc specific view functions
Those functions are pre-filled versions of the view functions above for the most common operations, like to get all the documents associated to an array of ids.
To access those, pass a design doc name as second argument
const db = getDbApi('some-db-name', 'some-design-doc-name')
viewCustom
viewByKeysCustom
viewByKey
viewFindOneByKey
viewByKeys
see lib/view_functions
If you find this module useful, consider making a PR to improve the documentation
Utils
buildQueryString
See also
you might want to consider using couchdb-nano, the offical (but bloated ;p) CouchDB NodeJS lib