Permalink
Browse files

feat: base adapter and mysql adapter with some tests

  • Loading branch information...
XadillaX committed Aug 8, 2016
1 parent 7ba63ac commit 6fc46b0995f3239de10c61721853a9c548f8770b
Showing with 295 additions and 7 deletions.
  1. +5 −2 Makefile
  2. +36 −0 lib/adapters/base.js
  3. +88 −0 lib/adapters/mysql.js
  4. +31 −0 lib/toshihiko.js
  5. +9 −5 package.json
  6. +24 −0 test/adapters/base.js
  7. +102 −0 test/adapters/mysql.js
@@ -9,8 +9,11 @@ clean:
install:
@npm install -d --registry=http://registry.npm.taobao.org/

test: install
@NODE_ENV=test $(MOCHA) -t $(TIMEOUT)
debug-test:
@NODE_ENV=test DEBUG=toshihiko:* $(MOCHA) -t $(TIMEOUT) --recursive

test:
@NODE_ENV=test $(MOCHA) -t $(TIMEOUT) --recursive

before-test-travis: install
@mysql -e 'create database myapp_test;' & \
@@ -0,0 +1,36 @@
/**
* XadillaX created at 2016-08-08 17:04:49 With ♥
*
* Copyright (c) 2016 Souche.com, all rights
* reserved.
*/
"use strict";

const cu = require("config.util");
const debug = require("debug")("toshihiko:adapter:base");
const EventEmitter = require("eventemitter2").EventEmitter2;

class Adapter extends EventEmitter {
constructor(parent, options) {
super();

Object.defineProperties(this, {
parent: {
value: parent,
writable: false,
configurable: false,
enumerable: false
},
options: {
value: cu.extendDeep({}, options || {}),
writable: true,
configurable: false,
enumerable: true
}
});

debug("created.", this);
}
}

module.exports = Adapter;
@@ -0,0 +1,88 @@
/**
* XadillaX created at 2016-08-08 17:04:12 With ♥
*
* Copyright (c) 2016 Souche.com, all rights
* reserved.
*/
"use strict";

const cu = require("config.util");
const debug = require("debug")("toshihiko:adapter:mysql");

const Adapter = require("./base");

function onConnection() {
this.emit("log", "A new MySQL connection from Toshihiko is set. ⁽⁽ଘ( ˙꒳˙ )ଓ⁾⁾");
}

class MySQLAdapter extends Adapter {
constructor(parent, options) {
super(parent, options);

this.options = cu.extendDeep({}, {
username: "",
password: "",
database: "toshihiko",
host: "localhost",
port: 3306
}, this.options);

const PASSWORD = this.options.password;
Object.defineProperties(this, {
username: {
value: this.options.username,
enumerable: true
},
database: {
value: this.options.database,
enumerable: true
}
});

delete this.options.username;
delete this.options.database;
delete this.options.password;

const opt = cu.extendDeep({}, this.options, {
user: this.username,
database: this.database,
password: PASSWORD
});

// try to require mysql adapter
let mysql;
if(!this.options.package) {
try {
mysql = require("mysql2");
} catch(e) {
debug("fallback to use mysql.");
mysql = require("mysql");
}
} else {
debug(`use package "${this.options.package}" as adapter`);
mysql = require(this.options.package);
}

Object.defineProperty(this, "mysql", {
value: mysql.createPool(opt),

enumerable: false,
writable: false,
configurable: false
});

// let mysql be compatibility with Toshihiko version 0.x
// set toshihiko.pool when using mysql
Object.defineProperty(parent, "pool", {
configurable: true,
enumerable: false,
get: () => this.mysql
});

this.mysql.on("connection", onConnection.bind(this));

debug("created.", this);
}
}

module.exports = MySQLAdapter;
@@ -0,0 +1,31 @@
/**
* XadillaX created at 2016-08-08 15:45:10 With ♥
*
* Copyright (c) 2016 Souche.com, all rights
* reserved.
*/
"use strict";

const _ = require("lodash");
const EventEmitter = require("eventemitter2").EventEmitter2;

class Toshihiko extends EventEmitter {
constructor(Adapter, options) {
super();

this.options = options || {};
const opt = _.clone(this.options, true);

// create the adapter
if(typeof Adapter === "string") {
Adapter = require(`./adapters/${Adapter}`);
}
this.adapter = new Adapter(this, options);

if(opt.cache) {
this.cache = Toshihiko.createCache(opt.cache);
}
}
}

module.exports = Toshihiko;
@@ -8,20 +8,24 @@
},
"dependencies": {
"async": "2.0.1",
"colors": "1.1.2",
"lodash": "4.14.1",
"mysql2": "1.0.0-rc.3",
"scarlet-task": "1.0.0"
"config.util": "^1.20.2-1",
"debug": "^2.2.0",
"eventemitter2": "^2.1.0",
"lodash": "4.14.1"
},
"devDependencies": {
"conventional-changelog-cli": "1.2.0",
"coveralls": "2.11.12",
"cz-conventional-changelog": "1.1.7",
"decache": "^4.1.0",
"ghooks": "1.3.2",
"istanbul": "1.0.0-alpha.2",
"jsxhint": "0.15.1",
"mocha": "3.0.1",
"mysql": "^2.11.1",
"mysql2": "^1.0.0-rc.9",
"should": "10.0.0",
"sync-runner": "^0.1.5",
"validate-commit-msg": "2.6.1"
},
"scripts": {
@@ -60,4 +64,4 @@
"pre-push": "npm test"
}
}
}
}
@@ -0,0 +1,24 @@
/**
* XadillaX created at 2016-08-08 17:29:52 With ♥
*
* Copyright (c) 2016 Souche.com, all rights
* reserved.
*/
"use strict";

require("should");

const Adapter = require("../../lib/adapters/base");

describe("🐣 adapters/base", function() {
it("should create a base adapter", function() {
const par = {};
const options = { foo: "bar" };
const adapter = new Adapter(par, options);

adapter.parent.should.be.eql(par);

adapter.options.should.deepEqual(options);
adapter.options.should.not.equal(options);
});
});
@@ -0,0 +1,102 @@
/**
* XadillaX created at 2016-08-08 17:46:49 With ♥
*
* Copyright (c) 2016 Souche.com, all rights
* reserved.
*/
"use strict";

const path = require("path");

const decache = require("decache");
const runSync = require("sync-runner");
const should = require("should");

const Adapter = require("../../lib/adapters/base");
const MySQLAdapter = require("../../lib/adapters/mysql");

describe("🐣 adapters/mysql", function() {
it("should be instanceof Adapter", function(done) {
const par = {};
const options = {};
const adapter = new MySQLAdapter(par, options);

adapter.should.be.instanceof(Adapter);
adapter.mysql.end(done);
});

it("should have correct position of username, database, password", function(done) {
const par = {};
const options = {
username: "username",
password: "pwd",
database: "test",

host: "127.0.0.1"
};
const adapter = new MySQLAdapter(par, options);

adapter.username.should.equal(options.username);
adapter.database.should.equal(options.database);
adapter.options.host.should.equal(options.host);
adapter.options.port.should.equal(3306);
adapter.mysql.config.connectionConfig.password.should.equal(options.password);

should.not.exists(adapter.options.username);
should.not.exists(adapter.options.password);
should.not.exists(adapter.options.database);

adapter.mysql.end(done);
});

it("should hijack parent's pool to be compatible", function(done) {
const par = {};
const adapter = new MySQLAdapter(par);
par.pool.should.equal(adapter.mysql);
par.pool.end(done);
});

describe("should use mysql2", function() {
it("when default", function(done) {
const Pool = require("mysql2/lib/pool");
const adapter = new MySQLAdapter({}, {});

adapter.mysql.should.be.instanceof(Pool);
adapter.mysql.end(done);
});

it("when use config", function(done) {
const Pool = require("mysql2/lib/pool");
const options = { package: "mysql2" };
const adapter = new MySQLAdapter({}, options);

adapter.mysql.should.be.instanceof(Pool);
adapter.mysql.end(done);
});
});

describe("should use mysql", function() {
it("when default with no mysql2", function(done) {
decache("mysql2");
decache("../../lib/adapters/mysql");
const MySQLAdapter_ = require("../../lib/adapters/mysql");
runSync("mv node_modules/mysql2 node_modules/mysql2.bak", path.resolve(__dirname, "../../"));

const adapter = new MySQLAdapter_({}, {});
runSync("mv node_modules/mysql2.bak node_modules/mysql2", path.resolve(__dirname, "../../"));

const Pool = require("mysql/lib/Pool");
adapter.mysql.should.be.instanceof(Pool);
adapter.mysql.end(done);
});

it("when use config", function(done) {
const Pool = require("mysql/lib/Pool");
const options = { package: "mysql" };
const adapter = new MySQLAdapter({}, options);

adapter.mysql.should.be.instanceof(Pool);
adapter.mysql.end(done);
});
});
});

0 comments on commit 6fc46b0

Please sign in to comment.