Implemented Transient connector

This commit is contained in:
Fabien Franzen 2014-08-30 10:53:10 +02:00
parent 170dc661f4
commit bd9895ebd6
5 changed files with 231 additions and 4 deletions

View File

@ -6,7 +6,7 @@ var fs = require('fs');
var async = require('async');
/**
* Initialize the Oracle connector against the given data source
* Initialize the Memory connector against the given data source
*
* @param {DataSource} dataSource The loopback-datasource-juggler dataSource
* @param {Function} [callback] The callback function

142
lib/connectors/transient.js Normal file
View File

@ -0,0 +1,142 @@
var util = require('util');
var Connector = require('loopback-connector').Connector;
var utils = require('../utils');
var crypto = require('crypto');
/**
* Initialize the Transient connector against the given data source
*
* @param {DataSource} dataSource The loopback-datasource-juggler dataSource
* @param {Function} [callback] The callback function
*/
exports.initialize = function initializeDataSource(dataSource, callback) {
dataSource.connector = new Transient(null, dataSource.settings);
dataSource.connector.connect(callback);
};
exports.Transient = Transient;
function Transient(m, settings) {
settings = settings || {};
if (typeof settings.generateId === 'function') {
this.generateId = settings.generateId.bind(this);
}
this.defaultIdType = settings.defaultIdType || String;
if (m instanceof Transient) {
this.isTransaction = true;
this.constructor.super_.call(this, 'transient', settings);
this._models = m._models;
} else {
this.isTransaction = false;
this.constructor.super_.call(this, 'transient', settings);
}
}
util.inherits(Transient, Connector);
Transient.prototype.getDefaultIdType = function() {
return this.defaultIdType;
};
Transient.prototype.getTypes = function() {
return ['db', 'nosql', 'transient'];
};
Transient.prototype.connect = function (callback) {
if (this.isTransaction) {
this.onTransactionExec = callback;
} else {
process.nextTick(callback);
}
};
Transient.prototype.generateId = function(model, data, idType) {
idType = idType || this.getDefaultIdType();
if (idType === Number || idType === 'number') {
return Math.floor(Math.random() * 10000); // max. 4 digits
} else {
return crypto.randomBytes(Math.ceil(24/2))
.toString('hex') // convert to hexadecimal format
.slice(0, 24); // return required number of characters
}
};
/*!
* Flush the cache - noop.
* @param {Function} callback
*/
Transient.prototype.flush = function (result, callback) {
process.nextTick(function () { callback && callback(null, result); });
};
Transient.prototype.create = function create(model, data, callback) {
var idName = this.idName(model);
if (idName) {
var props = this._models[model].properties;
var idType = props[idName] && props[idName].type;
var id = this.getIdValue(model, data) || this.generateId(model, data, idType);
id = (props[idName] && props[idName].type && props[idName].type(id)) || id;
this.setIdValue(model, data, id);
}
this.flush(id, callback);
};
Transient.prototype.save = function save(model, data, callback) {
this.flush(data, callback);
};
Transient.prototype.exists = function exists(model, id, callback) {
process.nextTick(function () { callback(null, false); }.bind(this));
};
Transient.prototype.find = function find(model, id, callback) {
process.nextTick(function () { callback(null, null); }.bind(this));
};
Transient.prototype.destroy = function destroy(model, id, callback) {
this.flush(null, callback);
};
Transient.prototype.all = function all(model, filter, callback) {
process.nextTick(function () { callback(null, []); });
};
Transient.prototype.destroyAll = function destroyAll(model, where, callback) {
if (!callback && 'function' === typeof where) {
callback = where;
where = undefined;
}
this.flush(null, callback);
};
Transient.prototype.count = function count(model, callback, where) {
process.nextTick(function () { callback(null, 0); });
};
Transient.prototype.update =
Transient.prototype.updateAll = function updateAll(model, where, data, cb) {
this.flush(null, cb);
};
Transient.prototype.updateAttributes = function updateAttributes(model, id, data, cb) {
if (!id) {
var err = new Error('You must provide an id when updating attributes!');
if (cb) {
return cb(err);
} else {
throw err;
}
}
this.setIdValue(model, data, id);
this.save(model, data, cb);
};
Transient.prototype.transaction = function () {
return new Transient(this);
};
Transient.prototype.exec = function (callback) {
this.onTransactionExec();
setTimeout(callback, 50);
};

View File

@ -12,10 +12,17 @@ module.exports = require('should');
}
*/
var ModelBuilder = require('../').ModelBuilder;
var Schema = require('../').Schema;
if (!('getSchema' in global)) {
global.getSchema = function () {
return new Schema('memory');
global.getSchema = function (connector, settings) {
return new Schema(connector || 'memory', settings);
};
}
if (!('getModelBuilder' in global)) {
global.getModelBuilder = function () {
return new ModelBuilder();
};
}

View File

@ -1,7 +1,7 @@
// This test written in mocha+should.js
var should = require('./init.js');
var db, Book, Chapter, Author, Reader;
var db, tmp, Book, Chapter, Author, Reader;
var Category, Job;
var Picture, PictureLink;
var Person, Address;

78
test/transient.test.js Normal file
View File

@ -0,0 +1,78 @@
var jdb = require('../');
var DataSource = jdb.DataSource;
var assert = require('assert');
var async = require('async');
var should = require('./init.js');
var db, TransientModel, Person, Widget, Item;
describe('Transient connector', function () {
before(function () {
db = getSchema('transient');
TransientModel = db.define('TransientModel', {}, { idInjection: false });
Person = TransientModel.extend('Person', {name: String});
Person.attachTo(db);
Widget = db.define('Widget', {name: String});
Item = db.define('Item', {
id: {type: Number, id: true}, name: String
});
});
it('should respect idInjection being false', function(done) {
should.not.exist(Person.definition.properties.id);
should.exist(Person.definition.properties.name);
Person.create({ name: 'Wilma' }, function(err, inst) {
should.not.exist(err);
inst.toObject().should.eql({ name: 'Wilma' });
Person.count(function(err, count) {
should.not.exist(err);
count.should.equal(0);
done();
});
});
});
it('should generate a random string id', function(done) {
should.exist(Widget.definition.properties.id);
should.exist(Widget.definition.properties.name);
Widget.definition.properties.id.type.should.equal(String);
Widget.create({ name: 'Thing' }, function(err, inst) {
should.not.exist(err);
inst.id.should.match(/^[0-9a-fA-F]{24}$/);
inst.name.should.equal('Thing');
Widget.findById(inst.id, function(err, widget) {
should.not.exist(err);
should.not.exist(widget);
done();
});
});
});
it('should generate a random number id', function(done) {
should.exist(Item.definition.properties.id);
should.exist(Item.definition.properties.name);
Item.definition.properties.id.type.should.equal(Number);
Item.create({ name: 'Example' }, function(err, inst) {
should.not.exist(err);
inst.id.should.be.a.number;
inst.name.should.equal('Example');
Item.count(function(err, count) {
should.not.exist(err);
count.should.equal(0);
done();
});
});
});
});