Skip to content

Commit

Permalink
Merge pull request #1 from bravi-software/support-knex-0.8
Browse files Browse the repository at this point in the history
Support knex 0.8
  • Loading branch information
maxcnunes committed Sep 18, 2015
2 parents fe3fb3c + 95fce66 commit 3883d32
Show file tree
Hide file tree
Showing 8 changed files with 152 additions and 111 deletions.
3 changes: 3 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ test:
- .:/usr/src/app
links:
- mysql:mysql
environment:
# DEBUG: knextancy:tenant


ci:
build: .
Expand Down
6 changes: 6 additions & 0 deletions lib/debug.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
var debug = require('debug');


module.exports = function (namespace) {
return debug('knextancy:' + (namespace || '*'));
};
84 changes: 84 additions & 0 deletions lib/knex-tenant-support.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
var knex = require('knex');
var _ = require('underscore');
var override = require('./override').override;
var before = require('./override').before;
var after = require('./override').after;
var debug = require('./debug')('client-multi-tenant');


exports.buildConfig = function (config, tenantId) {
var multitenantConfig = _.clone(config || {});

multitenantConfig.tenantId = tenantId;

var migrationsMultitenantConfig = _.clone(multitenantConfig.migrations || {});
multitenantConfig.migrations = _.extend(migrationsMultitenantConfig, {
// custom migration with the table name prefix
tableName: tenantId + '_' + (multitenantConfig.migrations.tableName || 'knex_migrations')
});

return multitenantConfig;
};


exports.install = function () {
Object.defineProperty(knex.Client.prototype, 'tenantId', {
get: function() {
return this.config.tenantId;
}
});

override(knex.Client.prototype.QueryBuilder.prototype, 'toSQL', after(function(sql) {
debug('knex.Client.prototype.QueryBuilder.prototype.toSQL', arguments);
sql.sql = applyTenant(sql.sql, this.client.tenantId);
return sql;
}));

override(knex.Client.prototype.Raw.prototype, 'set', before(function(sql, bindings) {
debug('knex.Client.prototype.Raw.prototype.set', arguments);
sql = applyTenant(sql, this.client.tenantId);
return [sql, bindings];
}));

override(knex.Client.prototype.SchemaBuilder.prototype, 'toSQL', after(function(sql) {
debug('knex.Client.prototype.SchemaBuilder.prototype.toSQL', arguments);
var client = this.client;

sql.forEach(function (sql) {
sql.sql = applyTenant(sql.sql, client.tenantId);
});

return sql;
}));

override(knex.Client.prototype.Runner.prototype, 'query', after(function(promise, originalArgs) {
debug('knex.Client.prototype.Runner.prototype.query', arguments);
var options = originalArgs[0].options;

var client = this.client;
return promise.then(function(result) {
if (!options || !options.nestTables) return result;

return result.map(function (row) {
var processedRow = {};

Object.keys(row).forEach(function (tableJoinName) {
processedRow[unapplyTenant(tableJoinName, client.tenantId)] = row[tableJoinName];
});

return processedRow;
});
});
}));
};


function unapplyTenant (sql, tenant) {
var regexp = new RegExp('^('+tenant+'+_)');
return sql.replace(regexp, '$_');
}


function applyTenant (sql, tenant) {
return sql.replace(/\$_/g, tenant + '_');
}
24 changes: 24 additions & 0 deletions lib/override.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* Based on http://me.dt.in.th/page/JavaScript-override
*/
module.exports.override = function (object, methodName, callback) {
object[methodName] = callback(object[methodName]);
};


module.exports.before = function (extraBehavior) {
return function(original) {
return function() {
return original.apply(this, extraBehavior.apply(this, arguments));
};
};
};


module.exports.after = function (extraBehavior) {
return function(original) {
return function() {
return extraBehavior.call(this, original.apply(this, arguments), arguments);
};
};
};
101 changes: 0 additions & 101 deletions lib/proxy-client-tenant.js

This file was deleted.

38 changes: 32 additions & 6 deletions lib/tenant.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,29 @@
var knex = require('knex'),
proxyClientTenant = require('./proxy-client-tenant'),
knexTenantSupport = require('./knex-tenant-support'),
Promise = require('rsvp').Promise;

var debug = require('./debug')('tenant');

var cache = {};
var waiting = {};

var isMultiTenantSupportInstalled = false;

module.exports = function (baseKnex, tenantId) {
if (!isMultiTenantSupportInstalled) {
try {
debug('installing knextancy');
knexTenantSupport.install();
isMultiTenantSupportInstalled = true;
} catch (e) {
console.error('Error installing knex multi tenant support', e, e.stack);
throw e;
}
}

return new Promise(function (resolve, reject) {
var result = cache[tenantId];
if (result) {
debug('getting knex for tenant %d from cache', tenantId);
resolve(result);
return;
}
Expand All @@ -19,11 +33,21 @@ module.exports = function (baseKnex, tenantId) {

promises.push({ resolve: resolve, reject: reject });

if (promises.length > 1) { return; }
if (promises.length > 1) {
debug('the knex for this tenant %d is already been built', tenantId);
return;
}

debug('building knex for new tenant %d', tenantId);
var proxyKnex = knex(knexTenantSupport.buildConfig(baseKnex.client.config, tenantId));

var proxyKnex = knex({ __client__: proxyClientTenant(baseKnex.client, tenantId)});
proxyKnex.tenantId = tenantId;
Object.defineProperty(proxyKnex, 'tenantId', {
get: function() {
return this.client.tenantId;
}
});

debug('initializing multi tenant database');
proxyKnex.migrate.latest().then(function () {
return proxyKnex.seed.run();
}).then(function () {
Expand All @@ -32,11 +56,13 @@ module.exports = function (baseKnex, tenantId) {
p.resolve(proxyKnex);
});
delete waiting[tenantId];
}).catch(function () {
}).catch(function (e) {
promises.forEach(function (p) {
p.reject(proxyKnex);
});
delete waiting[tenantId];

console.error('Error on initializing the multi tenant database', e, e.stack);
});
});
};
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@
"bugs": "https://github.com/bravi-software/knextancy/issues",
"license": "MIT",
"peerDependencies": {
"knex": "^0.7.3"
"knex": "^0.8.6"
},
"dependencies": {
"debug": "^2.2.0",
"rsvp": "^3.0.18",
"underscore": "^1.7.0"
},
Expand All @@ -42,6 +43,6 @@
"jshint": "^2.5.0",
"mocha": "^1.18.2",
"supertest": "^0.14.0",
"knex": "^0.7.3"
"knex": "^0.8.6"
}
}
2 changes: 0 additions & 2 deletions spec/tenant-queries.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,5 +64,3 @@ describe("tenant queries", function() {
});
});
});


0 comments on commit 3883d32

Please sign in to comment.