Skip to content

Commit

Permalink
Merge branch 'master' of github.com:geddy/model
Browse files Browse the repository at this point in the history
  • Loading branch information
mde committed Dec 14, 2014
2 parents 53317de + 17dfbdd commit c46657c
Show file tree
Hide file tree
Showing 13 changed files with 1,032 additions and 69 deletions.
1 change: 1 addition & 0 deletions Jakefile
Expand Up @@ -15,6 +15,7 @@ testTask('Model', function () {
this.testFiles.exclude('test/integration/adapters/sql/eager_assn.js');
this.testFiles.exclude('test/integration/adapters/sql/nested_eager_assn.js');
this.testFiles.exclude('test/integration/adapters/sql/postgres_common.js');
this.testFiles.exclude('test/integration/adapters/rest/server.js');
this.testFiles.exclude('test/config.js');
this.testFiles.exclude('test/db.json');
this.testFiles.exclude('test/db.sample.json');
Expand Down
2 changes: 2 additions & 0 deletions README.md
Expand Up @@ -54,6 +54,7 @@ Model currently implements adapters for:
* LevelDB
* In-memory
* Filesystem
* RESTfull Web-Services

### License

Expand Down Expand Up @@ -282,6 +283,7 @@ all of these but will put it in your `package.json` file for you:
- SQLite: `npm install sqlite3 --save`
- MongoDB: `npm install mongodb --save`
- LevelDB: `npm install level --save`
- REST: `npm install rest-js --save`

The in-memory, filesystem, and Riak adapters work out of the box and don't need any
additional libraries.
Expand Down
4 changes: 1 addition & 3 deletions lib/adapters/index.js
Expand Up @@ -76,15 +76,13 @@ adapters = new (function () {

this.create = function (name, config) {
var info = this.getAdapterInfo(name)
, ctorPath
, ctor;

if (!info) {
throw new Error('"' + name + '" is not a valid adapter.');
}

ctorPath = path.join(__dirname, info.path)
ctor = require(ctorPath).Adapter;
ctor = require('./' + info.path).Adapter;

return new ctor(config || {});
};
Expand Down
176 changes: 116 additions & 60 deletions lib/adapters/level/index.js
Expand Up @@ -36,14 +36,12 @@ if (!level && !multilevel) {

_baseConfig = {
db: '/data/level',
sublevel: '',
sublevel: null,
keyPrefix: true,
multilevel: {
port: 3000,
host: 'localhost',
manifest: '',
auth: false
}
port: null,
host: null,
manifest: null,
auth: null
};

var Adapter = function (options) {
Expand All @@ -55,6 +53,8 @@ var Adapter = function (options) {
this.client = null;
this.db = null;

this.isMultilevel = (this.config.port && this.config.host && multilevel);

this.init.apply(this, arguments);
};

Expand All @@ -72,62 +72,61 @@ utils.mixin(Adapter.prototype, new (function () {
if (config.sublevel) {
// Load sublevel, and set db
sublevel = utils.file.requireLocal('level-sublevel');
db = sublevel(db);
db = db.sublevel(config.sublevel);
this._db = sublevel(db);
this.db = this._db.sublevel(config.sublevel);
} else {
this._db = this.db = db;
}

this.db = db;
};

this._initMultilevel = function (config) {
var db
, con
, manifest;

if (config.multilevel.manifest) {
manifest = require(config.multilevel.manifest);
}

db = multilevel.client(manifest);

this.client = net.connect(config.multilevel.port, config.multilevel.host, function (err) {
if (err) throw err;
});
var manifest;

if (config.multilevel.auth) {
db.auth(config.multilevel.auth, function (err) {
if (err) throw err;
});
if (config.manifest) {
manifest = config.manifest;
if (typeof(manifest) === 'string') {
manifest = require(manifest);
}
}

this.client.pipe(db.createRpcStream()).pipe(this.client);

if (config.sublevel) {
this.db = db.sublevel(config.sublevel);
} else {
this.db = db;
}
this._db = multilevel.client(manifest);
};

this._generateKey = function (type, id) {
var keyPrefix = this.config.keyPrefix;
this._generateKey = function (type, id, reverse) {
var keyPrefix = this.config.keyPrefix
, key;

if (keyPrefix === true) {
return type + delimiter + id;

if (reverse) {
key = id.replace(type + delimiter, id);
}
else {
key = type + delimiter + id;
}
}
else if (keyPrefix === false) {
return id;
key = id;
}
else {
return keyPrefix + delimiter + id;
if (reverse) {
key = id.replace(keyPrefix + delimiter, id);
}
else {
key = keyPrefix + delimiter + id;
}
}

return key;
}

this._generateId = function (type, key) {
return this._generateKey(type, key, true);
}

this.init = function () {
var config = this.config;

if (multilevel) {
if (this.isMultilevel) {
this._initMultilevel(config);
} else {
this._initLevel(config);
Expand Down Expand Up @@ -196,6 +195,9 @@ utils.mixin(Adapter.prototype, new (function () {
if (filter(data)) {
inst = query.model.create(item.value, {scenario: query.opts.scenario});
inst.id = item.value.id;
if (!inst.id) {
inst.id = self._generateId(type, item.key);
}
inst._saved = true;
res.push(inst);
}
Expand Down Expand Up @@ -376,17 +378,22 @@ utils.mixin(Adapter.prototype, new (function () {

var drop = function () {
var type
, tableName;
, tableName
, batch;
if ((type = types.shift())) {
// tableName = utils.inflection.pluralize(c);
// tableName = utils.string.snakeize(tableName);

startKey = self._generateKey(type, '');
endKey = self._generateKey(type, '\xFF');
batch = [];

db.createReadStream({start: startKey, end: endKey})
.pipe(db.createWriteStream({ type: 'del' }))
.on('data', function (item) {
batch.push({ key: item.key, type: 'del' });
})
.on('close', function () {
drop();
db.batch(batch, drop);
});
}
else {
Expand All @@ -396,39 +403,88 @@ utils.mixin(Adapter.prototype, new (function () {
drop();
};

this.connect = function (callback) {
this._connectMultilevel = function (cb) {
var self = this
, cb = callback || function () {};
this.client.on('connect', function (err) {
, config
, con;

config = this.config;

function setDb() {
if(config.sublevel) {
self.db = self._db.sublevel(config.sublevel);
}
else {
self.db = self._db;
}
self.emit('connect');
cb();
}

this.client = net.connect(config.port, config.host, function (err) {
if (err) {
self.emit('error', err);
cb(err);
return cb(err);
}

if (config.auth) {
self._db.auth(config.auth, function (err) {
if (err) {
self.emit('error', err);
return cb(err);
}
setDb();
});
}
else {
self.emit('connect');
cb();
setDb();
}
});

this.client.pipe(this._db.createRpcStream()).pipe(this.client);
};

this.connect = function (callback) {
var self = this
, cb = callback || function () {};

if (this.isMultilevel) {
this._connectMultilevel(cb);
}
else {
setTimeout(function () {
self.emit('connect');
cb();
}, 0);
}
};

this.disconnect = function (callback) {
var self = this
, cb = callback || function () {};
this.client.on('close', function (err) {
if (err) {
self.emit('error', err);
cb(err);
}
else {
if (this.isMultilevel) {
process.nextTick(function () {
self._db.close();
self.emit('disconnect');
cb();
}
});
});
}
else {
this._db.close(function (err) {
if (err) {
self.emit('error', err);
cb(err);
}
else {
self.emit('disconnect');
cb();
}
});
}
};

})());

utils.mixin(Adapter.prototype, mr);

module.exports.Adapter = Adapter;

0 comments on commit c46657c

Please sign in to comment.