nano-repository

1.0.0 • Public • Published

nano-repository

Build Status Dependency Status Coverage Status

Working with CouchDB is a pretty pleasant experience, mostly because of the rather excellent nano library.

There are a couple of rough edges though, so what else could be better but an abstracton on top of an abstraction!

Examples

Create me a repository:

var Nano = require('nano'),
  Repository = require('nano-repository');
 
// set up Nano
var connection = new Nano('http://localhost:5984');
var db = connection.db.create('my_db');
 
// set up repo
var repository = new Repository(db);
 

CRUD operations

var document = {foo: 'bar'};
 
// create
repository.save(document, function(error, result) {
    // document now has _id, _rev and created_at properties
});
 
// retrieve
repository.findById(id, function(error, document) {
    // document has been fetched
});
 
// update
repository.save(document, function(error, result) {
    // if previously saved, document now has updated_at properties
    // and _rev has been incremented
});
 
// delete
repository.remove(document, function(error) {
    // document has been deleted
});

Attachments

Add files to your documents:

repository.addAttachment(document, attachmentName, pathToFile, mimeType, function(error, body) {
  // file has now been attached
});

Retrieve attachments:

repository.findAttachment(document, name, function(error, body) {
  // body contains the attachment data
});

Attachment versions

The attachment version is dependent on the document version. E.g if you will pardon the pyramid of doom:

var attachmentName = 'myFile';
 
// add the first version of the attachment
repository.addAttachment(document, attachmentName, pathToFile, mimeType, function(error, body) {
  // now document._rev = 2
 
  // add the second it again:
  repository.addAttachment(document, attachmentName, pathToFile, mimeType, function(error, body) {
    // now document._rev = 3
 
    // we now have two revisions of 'myFile' that we can access:
    repository.findAttachment({_id: document._id, _rev: 2}, attachmentName, function(error, body) {
      // body contains the first version of myFile
    });
    repository.findAttachment({_id: document._id, _rev: 3}, attachmentName, function(error, body) {
      // body contains the second version
    });
  });
});

Streaming attachments

For the performance/memory conscious, stream files to your documents with the 4x argument version of Repository.addAttachment:

var fileStream = fs.createReadStream(pathToFile);
 
fileStream.pipe(repository.addAttachment(document, attachmentName, mimeType, function(error, body) {
  // file has now been attached
}));

...and retrieve them:

repository.streamAttachmentTo(document, name, writeStream);

Views

Views are accessed by extra methods on the Repository. To create your views, first create a view template file, usally with the .json extension.

The template file looks like this (n.b. feel free to include reduce functions if you need them):

{
  "views": {
    "all": {
      "map": "function(doc) {if(doc.name) emit(null, doc)}"
    },
    "byName": {
      "map": "function(doc) {if(doc.name) emit(doc.name, doc)}"
    }
  }
}

Update/create the views:

var repository = new Repository(db);
repository.updateViews('path/to/views.json', function(error) {
  // views are now ready to use
});

View methods are dynamically created:

repository.findAll(function(error, list) {
  // list contains all documents from this collection
});

Method names are chosen by capitalising the first letter of the view name and prepending find to it.

So the view mapping file contained a view named all - this was turned into findAll, similarly the view named byName was turned into a method named findByName.

Arguments are also supported:

repository.findByName('bob', function(error, list) {
  // list contains all documents where doc.name == 'bob'
});

The code that makes up your view is hashed - the hash is stored along with the views. The next time you call Repository.updateViews the hashes are compared - it they've changed then the views are recreated automatically.

This means it's save to call Repository.updateViews every time you start your app - they'll only get altered if you change the code in your view file.

Get out of my console.log

You can pass an alternative logging implementation into the constructor and the repository will use that instead, as long as it supports .info, .warn, etc methods.

var Nano = require('nano'),
  Logger = require('winston').Logger,
  logger = new Logger(..);
 
//.. set up Nano as usual
 
var repository = new Repository(db, logger);

Todo

  1. Retrieving specific document versions.
  2. Work out if I've missed the point somehow. Probably.

Readme

Keywords

none

Package Sidebar

Install

npm i nano-repository

Weekly Downloads

6

Version

1.0.0

License

none

Last publish

Collaborators

  • achingbrain