node package manager



Build Status

Experimental real-time storage API for MongoDB over


  • MongoDB support
  • Store and retrieve objects
  • Subscribe to objects
  • Subscribe to queries
  • In-memory storage for development
  • Complete mock for unit tests


Repo event flow


The client provides the API to access the database.


The client communicates with the storage over But any other event emitter providing .emit, .on, .off will work as transport layer as long as it executes callbacks on the client side.


The storage handles changes and manages subscriptions to objects and queries. It distributes update notification to all connected clients. The database is accessed through a simple storage layer (backend).


Repo provides a backend for MongoDB and one implementing an in-memory storage. The in-memory backend can be used for development and as a mock for unit tests.

It assumes that only repo accesses the database. It won't provide real-time updates for objects changed in other ways.


Repo supports a subset of MongoDB queries.

It sends real-time notifications when new objects match a subscribed query and when objects from the result set don't match the query anymore. This feature is implemented with qry and works with both the MongoDB and the in-memory backend.

Please check qry for the supported query operators.

Access / Authentication

Is planed but currently not supported.


Repo is currently tested with Phantom.js only.


Node (server side)

npm install repo


component install manuelstofer/repo

Client connection

var storage = require('repo'),
    client  = storage.client({
        socket: io.connect('http://localhost')


var storage = require('repo'),
    client  = storage.mock(),


The client API provides following methods:

  • get
  • put
  • del
  • query


The Example below retrieves the object with _id 10, without following real-time notifications:

client.get(10, function (notification) {

Update notifications

The callback can return a function to receive real-time updates. This requires manual unsubscription. The callback gets an unsub function as second argument for this purpose.

client.get(10, function (notification, unsub) {
    return function (notification) {
        if (notification.event === 'change') {
            console.log('object changed:', notification.doc);
        if (notification.event === 'del') {

Callback objects

Its also supported to return an object with the events you are interested in as keys.

client.get(10, function (notification, unsub) {
    return {
        change: function (notification) {
            console.log('changed to', notification.doc);
        del: function (notification) {
            console.log('object was deleted');


Will update / insert an object. If the object has an _id attribute its treated as update. Otherwise its an insert. The update notification works the same way as described for the get method.

var obj = {
    name: 'repo',
    version: 'experimental'
client.put(obj, function (notification, unsub) {
    return {
        del: function (notification) {
            console.log('object deleted');


Deletes an object

client.del(10, function (notification) {
    console.log('the object with id 10 was deleted');


Repo can be queried with MongoDB queries. Please check the MongoDB reference for the query format and qry for supported operators.

// query for objects with attribute tag equal to hello
client.query({tag: 'hello'}, function (notification, unsub) {
    return {
        change: function (notification) {
            console.log('changed', notification.doc);
        match: function (notification) {
            console.log('new result', notification.doc);
        unmatch: function (notification) {
            console.log('object does match any more');

Queries need manual unsubscription as well.


Following example will create a server for Repo with Express, and MongoDB

var express     = require('express'),
    app         = express(),
    http        = require('http'),
    mongodb     = require('mongodb'),
    server      = http.createServer(app),
    io          = require('').listen(server),
    storage     = require('../src/storage'),
    backend     = require('../src/backends/mongo'),
    mongoServer = new mongodb.Server(
    connector   = new mongodb.Db(
        { safe: true }
    ); (error, client) {
    var collection = new mongodb.Collection(client, 'test');
    console.log('connected to mongodb');
    var storageApi = storage({
        backend: backend({collection: collection}),
        debug: true
    io.sockets.on('connection', storageApi.addClient);
app.configure(function () {
    app.use(express.static(__dirname + '/public'));

The documentation for the MongoDB connection options can be found here