Skip to content

Commit

Permalink
Merge pull request #8 from mdpauley/master
Browse files Browse the repository at this point in the history
added tingodb adapter
  • Loading branch information
biggora committed Sep 16, 2013
2 parents c912448 + 4475e77 commit 45d6b3d
Show file tree
Hide file tree
Showing 2 changed files with 239 additions and 1 deletion.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/node_modules/
/tests/coverage/
/tests/coverage/
.DS_Store
237 changes: 237 additions & 0 deletions lib/adapters/tingodb.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
/**
* Module dependencies
* mongodb adapter with a few tweaks to run tingodb
*/
var tingodb = require('tingodb');
var fs = require('fs');

exports.initialize = function initializeSchema(schema, callback) {
if (!tingodb)
return;
var s = schema.settings;

s.database = s.database || '/db/data';
s.nativeObjectID = s.nativeObjectID || false;
s.cacheSize = s.cacheSize || 1000;
s.cacheMaxObjSize = s.cacheMaxObjSize || 1024;
s.searchInArray = s.searchInArray || false;

schema.adapter = new TingoDB(s, schema, callback);
};

function TingoDB(s, schema, callback) {
this.name = 'tingodb';
this._models = {};
this.collections = {};

new tingodb.Db(s.database, s).open(function(err, client) {
if (err)
throw err;

if(client)
this.client = client;
schema.client = client;
callback();
}.bind(this));
}

TingoDB.prototype.define = function(descr) {
if (!descr.settings)
descr.settings = {};
var self = this;
this._models[descr.model.modelName] = descr;
setTimeout(function() {
Object.keys(descr.properties).forEach(function(k) {
if (typeof descr.properties[k].index !== 'undefined' || typeof descr.properties[k].unique !== 'undefined') {
var fields = {}, params = {};
fields[k] = 1;
params['name'] = '_' + k + '_';
if (typeof descr.properties[k].unique !== 'undefined') {
params['unique'] = true;
}
self.collection(descr.model.modelName).ensureIndex(fields, params);
}
});
}, 1000);
};

TingoDB.prototype.defineProperty = function(model, prop, params) {
this._models[model].properties[prop] = params;
};

TingoDB.prototype.collection = function(name) {
if (!this.collections[name]) {
this.collections[name] = this.client.Collection(this.client, name);
}
return this.collections[name];
};

TingoDB.prototype.ensureIndex = function(model, fields, params, callback) {
this.collection(model).ensureIndex(fields, params);
return callback(null);
};

TingoDB.prototype.create = function(model, data, callback) {
if (data.id === null) {
delete data.id;
}
this.collection(model).insert(data, {}, function(err, m) {
callback(err, err ? null : m[0]._id);
});
};

TingoDB.prototype.save = function(model, data, callback) {
var id = data.id;
this.collection(model).update({_id: id}, data, function(err) {
callback(err);
});
};

TingoDB.prototype.exists = function(model, id, callback) {
this.collection(model).findOne({_id: id}, function(err, data) {
callback(err, !err && data);
});
};

TingoDB.prototype.findById = function findById(model, id, callback) {
this.collection(model).findOne({_id: id}, function(err, data) {
if (data)
data.id = id;
callback(err, data);
});
};

TingoDB.prototype.updateOrCreate = function updateOrCreate(model, data, callback) {
var adapter = this;
if (!data.id)
return this.create(data, callback);
this.find(model, data.id, function(err, inst) {
if (err)
return callback(err);
if (inst) {
adapter.updateAttributes(model, data.id, data, callback);
} else {
delete data.id;
adapter.create(model, data, function(err, id) {
if (err)
return callback(err);
if (id) {
data.id = id;
delete data._id;
callback(null, data);
} else {
callback(null, null); // wtf?
}
});
}
});
};

TingoDB.prototype.destroy = function destroy(model, id, callback) {
this.collection(model).remove({_id: id}, callback);
};


TingoDB.prototype.remove = function remove(model, filter, callback) {
var cond = buildWhere(filter.where);
this.collection(model).remove(cond, callback);
};

TingoDB.prototype.all = function all(model, filter, callback) {
if (!filter) {
filter = {};
}
var query = {};
if (filter.where) {
query = buildWhere(filter.where);
}
var cursor = this.collection(model).find(query);

if (filter.order) {
var keys = filter.order;
if (typeof keys === 'string') {
keys = keys.split(',');
}
var args = {};
for (index in keys) {
var m = keys[index].match(/\s+(A|DE)SC$/);
var key = keys[index];
key = key.replace(/\s+(A|DE)SC$/, '').trim();
if (m && m[1] === 'DE') {
args[key] = -1;
} else {
args[key] = 1;
}
}
cursor.sort(args);
}
if (filter.limit) {
cursor.limit(filter.limit);
}
if (filter.skip) {
cursor.skip(filter.skip);
} else if (filter.offset) {
cursor.skip(filter.offset);
}
cursor.toArray(function(err, data) {
if (err)
return callback(err);
callback(null, data.map(function(o) {
o.id = o._id;
return o;
}));
});
};

TingoDB.prototype.destroyAll = function destroyAll(model, callback) {
this.collection(model).remove({}, callback);
};

TingoDB.prototype.count = function count(model, callback, filter) {
var cond = buildWhere(filter);
this.collection(model).count(cond, callback);
};

TingoDB.prototype.updateAttributes = function updateAttrs(model, id, data, callback) {
this.collection(model).findAndModify({_id: id}, [['_id', 'asc']], {$set: data}, {}, callback);
};

TingoDB.prototype.disconnect = function() {
this.client.close();
};

function buildWhere(filter) {
var query = {};
Object.keys(filter).forEach(function(k) {
var cond = filter[k];
var spec = false;
if (k === 'id') {
k = '_id';
}
if (cond && cond.constructor.name === 'Object') {
spec = Object.keys(cond)[0];
cond = cond[spec];
}
if (spec) {
if (spec === 'between') {
query[k] = {$gte: cond[0], $lte: cond[1]};
} else {
query[k] = {};
spec = spec === 'inq' ? 'in' : spec;
spec = spec === 'like' ? 'regex' : spec;
if (spec === 'nlike') {
query[k]['$not'] = new RegExp(cond, 'i');
} else {
query[k]['$' + spec] = cond;
}
}
} else {
if (cond === null) {
query[k] = {$type: 10};
} else {
query[k] = cond;
}
}
});
return query;
}

0 comments on commit 45d6b3d

Please sign in to comment.