A ridiculously simple Object Mapper for Node running on top of CouchDB.
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.



Endtable is an experimental ORM built on top of Node.js and CouchDB.

The concept? long-lived, self-monitoring, objects that persist only periodically as modifications are made to them.

This paradigm reduces the frequency with which writes are made to the database, and works well for domains such as games.

The Engine Object

A single engine object is instantiated and passed as a dependency to an Endtable Class:

var engine = new endtable.Engine({
	database: 'people_example',
	host: 'localhost',
	user: '',
	password: '',
	errorCallback: function(error) {
		// When views aren't found they raise a warning.

The Error Callback

Errors that occur in Endtable are propagated up to the errorCallback passed to the Engine's constructor.

Error objects provide the following information:

  • error.error the raw error message.
  • error.reason the reason for the error.
  • error.raisedByObject the underlying object that raised the error.
  • error.raisedByMethod the method that caused the error.
  • error.raisedByParameters the parameters passed to the method that caused the error.

Endtable Classes

Endtable Classes describe the ORM-backed objects.

var Dog = endtable.Object.extend(
		bark: function() {
		engine: engine,
		type: 'dog',
		customViews: [
		function lowerName(doc) {
		function otherNamedView(doc) { ... }
  • The first parameter contains all the methods that will be inherited by objects that instantiate the class.
  • The second parameter provides meta information:
    • engine is an instance of the Endtable Engine described previously.
    • type represents the corresponding CouchDB resource name.
    • customViews is an array containing custom view functions to be created on the couchdb server
      • all the functions must be named functions

Creating ORM-Backed Objects

Once you've created some Endtable Classes simply instantiate them to create auto-persisting CouchDB-backed objects.

var dog = new Dog({
	name: 'Spike',
	owner: 'Benjamin Coe',
	coat: 'soft'

var dog2 = new Dog({
	name: 'Fluffy',
	owner: 'Eric Brown',
	coat: 'rough'
}, function(err, message) {
	// Called after the first save.

The first parameter passed to the constructor provides the instance variables for the object.

An optional callback can be provided for the second parameter and will be executed the first time the object persists to CouchDB.

Loading Objects

You can lookup objects based on any of their keys.

Simply call the load method on an Endtable Class:

	keys: ['owner', 'coat'],
	key: ['Benjamin Coe', 'soft']
}, function(error, obj) {
	if (!error) {
  • keys indicates the keys that an object will be looked up by. A CouchDB view will be generated to allow for this lookup.
  • key is a set of concrete values that correspond with the keys described in keys.

You can also load objects based on a range of values.

	keys: 'age',
	startkey: 28,
	endkey: 50
}, function(error, obj) {
	if (!error) {
		for (var i = 0; i < obj.length; i++) {

This will load individuals with an age ranging from 28 to 50.

You can also load an object with a custom view function applied to it.

	keys: 'name',
    customView: 'lowerName'
}, function(error, obj) {
	if (!error) {
		for (var i = 0; i < obj.length; i++) {
  • customView is the name of a custom view function you defined when you defined the object
  • You can add in other parameters to filter the results as shown in previous examples


Run node examples/person.js to get an idea of Endtable in action.

Contributing to Endtable

  • Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
  • Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
  • Fork the project
  • Start a feature/bugfix branch
  • Commit and push until you are happy with your contribution
  • Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
  • Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.


Copyright (c) 2011 Benjamin Coe. See LICENSE.txt for further details.