js-junk-bucket-repo/couchdb.js
/**
* @module couchdb
*/
const nano = require( "nano" )
const { es6_node } = require( './index' )
/**
* A single CouchDB instance to communicate with over a well defined URL. Exposes asynchronous management of database
* wide operations such as manipulating databases.
*
* @type CouchDB.Service
*/
class Service {
/**
* Declares a new service to attempt to communicate with
* @param {string} host the URL of the CouchDB instnaces to be communciated with
*/
constructor( host = "http://localhost:5984" ){
this.client = nano( host )
}
/**
* Creates a new database if the database doesn't exist. If the database does exist it's considered an error
*
* @param name {string} Name of the database to be created
* @return {Promise} completed when the database is created
* @throws Error if the database exists
*/
create_db( name ) {
return es6_node( (cb ) => this.client.db.create( name, cb ) )
}
/**
* Enumerates all databases within the represenetd CouchDB system
* @return {Promise<Array<String>>} the names of the database existing within the represented CouchDB service
*/
list_dbs(){
return es6_node( ( cb ) => this.client.db.list( cb ) )
}
/**
* Creates a new database by the given name if it doesn't exist, otherwise returns a wrapper around the database
*
* @return {Promise<Database>} a promise for the database representation
*/
async ensure_db_exists( name ){
const dbs = await this.list_dbs()
if( !dbs.includes(name) ){
await this.create_db( name )
}
return new Database( this.client.use( name ) )
}
}
/**
* Encapsulates the CouchDB operations.
*
* @interface
*/
class Database {
constructor( client ) {
this.client = client
}
insert( document ) {
return es6_node( ( cb ) => this.client.insert( document, cb ) )
}
get_by_id( id, params ){
return es6_node( ( cb ) => this.client.get( id, params, cb ) )
}
/**
* Locates the given document by ID if it exists, otherwise return null
*
* @param id the _id property of the database to be resolved
* @param params optionally additional parameters to send the CouchDB during this operation
* @return {Promise) A promise to resolve the document or null if the document doesn't exist.
*/
maybe_by_id( id, params ){
return es6_node( ( cb ) => {
this.client.get( id, params, ( err, data ) => {
if( err ) {
if( err.statusCode == 404 ) { return cb( null, null ) }
return cb( err )
} else {
return cb( err, data )
}
})
})
}
view( design, name, params ){
return es6_node( ( cb ) => this.client.view( design, name, params, cb ) )
}
/**
* Retrieves the given document by ID, then modifies the document, then writes the document back.
*
* @param id {String} the ID of the document to be modified
* @param modifier { function( originalDocument ) = Promise} a function to promise a modified document
* @return a promise to update the given document
*/
async update_by_id( id, modifier ){
const document = await this.get_by_id( id );
const modified = await modifier( document );
return await this.insert( modified )
}
/**
* Updates the document if it exists or inserts the given document if the document doesn't exist
*
* @param id {String} the _id of the document to be modified
* @param generator { function() = Promise } A promise gneerator to create a new document for insert
* @param updater { function( originalDocument ) = Promise} a promise generator to modify the original document to be stored
* @return the results fo the insert or update
*/
async upsert( id, generator, updater ){
const document = await this.get_by_id( id )
if( document ){
const modified = await updater( document )
return await this.insert(modified)
} else {
const newDoc = await generator()
return await this.insert(newDoc)
}
}
/**
* Checks if a document with a given ID exists
*
* @param id {String} the _id of the document in question
* @return true if the document exists, otherwise false
*/
async exists( id ){
const document = this.maybe_by_id(id);
return null == document;
}
}
module.exports = {
Service,
Database
};