Merge pull request #2 from ErisDS/bookshelf-knex-update

Updating to bookshelf 0.5.7 & knex 0.4.11
This commit is contained in:
Hannah Wolfe 2013-10-17 10:49:28 -07:00
commit 491651da59
14 changed files with 85 additions and 85 deletions

View File

@ -2,21 +2,21 @@ var when = require('when'),
_ = require('underscore'), _ = require('underscore'),
migration = require('../migration'), migration = require('../migration'),
client = require('../../models/base').client, client = require('../../models/base').client,
knex = require('../../models/base').Knex, knex = require('../../models/base').knex,
exporter; exporter;
function getTablesFromSqlite3() { function getTablesFromSqlite3() {
return knex.Raw("select * from sqlite_master where type = 'table'").then(function (response) { return knex.raw("select * from sqlite_master where type = 'table'").then(function (response) {
return _.reject(_.pluck(response, 'tbl_name'), function (name) { return _.reject(_.pluck(response[0], 'tbl_name'), function (name) {
return name === 'sqlite_sequence'; return name === 'sqlite_sequence';
}); });
}); });
} }
function getTablesFromMySQL() { function getTablesFromMySQL() {
return knex.Raw('show tables').then(function (response) { return knex.raw("show tables").then(function (response) {
return _.flatten(_.map(response, function (entry) { return _.flatten(_.map(response[0], function (entry) {
return _.values(entry); return _.values(entry);
})); }));
}); });

View File

@ -1,5 +1,5 @@
var when = require('when'), var when = require('when'),
knex = require('../../models/base').Knex, knex = require('../../models/base').knex,
up, up,
down; down;
@ -7,7 +7,7 @@ up = function () {
return when.all([ return when.all([
knex.Schema.createTable('posts', function (t) { knex.schema.createTable('posts', function (t) {
t.increments().primary(); t.increments().primary();
t.string('uuid', 36).notNull(); t.string('uuid', 36).notNull();
t.string('title', 150).notNull(); t.string('title', 150).notNull();
@ -30,7 +30,7 @@ up = function () {
t.integer('published_by').nullable(); t.integer('published_by').nullable();
}), }),
knex.Schema.createTable('users', function (t) { knex.schema.createTable('users', function (t) {
t.increments().primary(); t.increments().primary();
t.string('uuid', 36).notNull(); t.string('uuid', 36).notNull();
t.string('name', 150).notNull(); t.string('name', 150).notNull();
@ -54,7 +54,7 @@ up = function () {
t.integer('updated_by').nullable(); t.integer('updated_by').nullable();
}), }),
knex.Schema.createTable('roles', function (t) { knex.schema.createTable('roles', function (t) {
t.increments().primary(); t.increments().primary();
t.string('uuid', 36).notNull(); t.string('uuid', 36).notNull();
t.string('name', 150).notNull(); t.string('name', 150).notNull();
@ -65,13 +65,13 @@ up = function () {
t.integer('updated_by').nullable(); t.integer('updated_by').nullable();
}), }),
knex.Schema.createTable('roles_users', function (t) { knex.schema.createTable('roles_users', function (t) {
t.increments().primary(); t.increments().primary();
t.integer('role_id').notNull(); t.integer('role_id').notNull();
t.integer('user_id').notNull(); t.integer('user_id').notNull();
}), }),
knex.Schema.createTable('permissions', function (t) { knex.schema.createTable('permissions', function (t) {
t.increments().primary(); t.increments().primary();
t.string('uuid', 36).notNull(); t.string('uuid', 36).notNull();
t.string('name', 150).notNull(); t.string('name', 150).notNull();
@ -84,19 +84,19 @@ up = function () {
t.integer('updated_by').nullable(); t.integer('updated_by').nullable();
}), }),
knex.Schema.createTable('permissions_users', function (t) { knex.schema.createTable('permissions_users', function (t) {
t.increments().primary(); t.increments().primary();
t.integer('user_id').notNull(); t.integer('user_id').notNull();
t.integer('permission_id').notNull(); t.integer('permission_id').notNull();
}), }),
knex.Schema.createTable('permissions_roles', function (t) { knex.schema.createTable('permissions_roles', function (t) {
t.increments().primary(); t.increments().primary();
t.integer('role_id').notNull(); t.integer('role_id').notNull();
t.integer('permission_id').notNull(); t.integer('permission_id').notNull();
}), }),
knex.Schema.createTable('settings', function (t) { knex.schema.createTable('settings', function (t) {
t.increments().primary(); t.increments().primary();
t.string('uuid', 36).notNull(); t.string('uuid', 36).notNull();
t.string('key', 150).notNull().unique(); t.string('key', 150).notNull().unique();
@ -107,7 +107,7 @@ up = function () {
t.dateTime('updated_at').nullable(); t.dateTime('updated_at').nullable();
t.integer('updated_by').nullable(); t.integer('updated_by').nullable();
}), }),
knex.Schema.createTable('tags', function (t) { knex.schema.createTable('tags', function (t) {
t.increments().primary(); t.increments().primary();
t.string('uuid', 36).notNull(); t.string('uuid', 36).notNull();
t.string('name', 150).notNull(); t.string('name', 150).notNull();
@ -120,30 +120,31 @@ up = function () {
t.integer('created_by').notNull(); t.integer('created_by').notNull();
t.dateTime('updated_at').nullable(); t.dateTime('updated_at').nullable();
t.integer('updated_by').nullable(); t.integer('updated_by').nullable();
}), })
knex.Schema.createTable('posts_tags', function (t) { ]).then(function () {
return knex.schema.createTable('posts_tags', function (t) {
t.increments().primary(); t.increments().primary();
t.integer('post_id').notNull().unsigned().references('id').inTable('posts'); t.integer('post_id').notNull().unsigned().references('id').inTable('posts');
t.integer('tag_id').notNull().unsigned().references('id').inTable('tags'); t.integer('tag_id').notNull().unsigned().references('id').inTable('tags');
}) });
]); });
}; };
down = function () { down = function () {
return when.all([ return when.all([
knex.Schema.dropTableIfExists('posts_tags'), knex.schema.dropTableIfExists('posts_tags'),
knex.Schema.dropTableIfExists('roles_users'), knex.schema.dropTableIfExists('roles_users'),
knex.Schema.dropTableIfExists('permissions_users'), knex.schema.dropTableIfExists('permissions_users'),
knex.Schema.dropTableIfExists('permissions_roles'), knex.schema.dropTableIfExists('permissions_roles'),
knex.Schema.dropTableIfExists('users') knex.schema.dropTableIfExists('users')
]).then(function () { ]).then(function () {
return when.all([ return when.all([
knex.Schema.dropTableIfExists('roles'), knex.schema.dropTableIfExists('roles'),
knex.Schema.dropTableIfExists('settings'), knex.schema.dropTableIfExists('settings'),
knex.Schema.dropTableIfExists('permissions'), knex.schema.dropTableIfExists('permissions'),
knex.Schema.dropTableIfExists('tags'), knex.schema.dropTableIfExists('tags'),
knex.Schema.dropTableIfExists('posts') knex.schema.dropTableIfExists('posts')
]); ]);
}); });
}; };

View File

@ -3,7 +3,7 @@ var _ = require('underscore'),
when = require('when'), when = require('when'),
series = require('when/sequence'), series = require('when/sequence'),
errors = require('../../errorHandling'), errors = require('../../errorHandling'),
knex = require('../../models/base').Knex, knex = require('../../models/base').knex,
defaultSettings = require('../default-settings'), defaultSettings = require('../default-settings'),
Settings = require('../../models/settings').Settings, Settings = require('../../models/settings').Settings,
@ -30,7 +30,7 @@ function getDefaultDatabaseVersion() {
// The migration version number according to the database // The migration version number according to the database
// This is what the database is currently at and may need to be updated // This is what the database is currently at and may need to be updated
function getDatabaseVersion() { function getDatabaseVersion() {
return knex.Schema.hasTable('settings').then(function (exists) { return knex.schema.hasTable('settings').then(function (exists) {
// Check for the current version from the settings table // Check for the current version from the settings table
if (exists) { if (exists) {
// Temporary code to deal with old databases with currentVersion settings // Temporary code to deal with old databases with currentVersion settings

View File

@ -1,4 +1,4 @@
var GhostBookshelf, var ghostBookshelf,
Bookshelf = require('bookshelf'), Bookshelf = require('bookshelf'),
when = require('when'), when = require('when'),
moment = require('moment'), moment = require('moment'),
@ -8,16 +8,15 @@ var GhostBookshelf,
Validator = require('validator').Validator, Validator = require('validator').Validator,
sanitize = require('validator').sanitize; sanitize = require('validator').sanitize;
// Initializes Bookshelf as its own instance, so we can modify the Models and not mess up // Initializes a new Bookshelf instance, for reference elsewhere in Ghost.
// others' if they're using the library outside of ghost. ghostBookshelf = Bookshelf.initialize(config[process.env.NODE_ENV || 'development'].database);
GhostBookshelf = Bookshelf.Initialize('ghost', config[process.env.NODE_ENV || 'development'].database); ghostBookshelf.client = config[process.env.NODE_ENV].database.client;
GhostBookshelf.client = config[process.env.NODE_ENV].database.client;
GhostBookshelf.validator = new Validator(); ghostBookshelf.validator = new Validator();
// The Base Model which other Ghost objects will inherit from, // The Base Model which other Ghost objects will inherit from,
// including some convenience functions as static properties on the model. // including some convenience functions as static properties on the model.
GhostBookshelf.Model = GhostBookshelf.Model.extend({ ghostBookshelf.Model = ghostBookshelf.Model.extend({
hasTimestamps: true, hasTimestamps: true,
@ -145,7 +144,7 @@ GhostBookshelf.Model = GhostBookshelf.Model.extend({
*/ */
findAll: function (options) { findAll: function (options) {
options = options || {}; options = options || {};
return GhostBookshelf.Collection.forge([], {model: this}).fetch(options); return ghostBookshelf.Collection.forge([], {model: this}).fetch(options);
}, },
browse: function () { browse: function () {
@ -212,4 +211,4 @@ GhostBookshelf.Model = GhostBookshelf.Model.extend({
}); });
module.exports = GhostBookshelf; module.exports = ghostBookshelf;

View File

@ -1,10 +1,10 @@
var GhostBookshelf = require('./base'), var ghostBookshelf = require('./base'),
User = require('./user').User, User = require('./user').User,
Role = require('./role').Role, Role = require('./role').Role,
Permission, Permission,
Permissions; Permissions;
Permission = GhostBookshelf.Model.extend({ Permission = ghostBookshelf.Model.extend({
tableName: 'permissions', tableName: 'permissions',
@ -14,7 +14,7 @@ Permission = GhostBookshelf.Model.extend({
validate: function () { validate: function () {
// TODO: validate object_type, action_type and object_id // TODO: validate object_type, action_type and object_id
GhostBookshelf.validator.check(this.get('name'), "Permission name cannot be blank").notEmpty(); ghostBookshelf.validator.check(this.get('name'), "Permission name cannot be blank").notEmpty();
}, },
roles: function () { roles: function () {
@ -26,7 +26,7 @@ Permission = GhostBookshelf.Model.extend({
} }
}); });
Permissions = GhostBookshelf.Collection.extend({ Permissions = ghostBookshelf.Collection.extend({
model: Permission model: Permission
}); });

View File

@ -11,9 +11,9 @@ var Post,
config = require('../../../config'), config = require('../../../config'),
Tag = require('./tag').Tag, Tag = require('./tag').Tag,
Tags = require('./tag').Tags, Tags = require('./tag').Tags,
GhostBookshelf = require('./base'); ghostBookshelf = require('./base');
Post = GhostBookshelf.Model.extend({ Post = ghostBookshelf.Model.extend({
tableName: 'posts', tableName: 'posts',
@ -38,7 +38,7 @@ Post = GhostBookshelf.Model.extend({
}, },
validate: function () { validate: function () {
GhostBookshelf.validator.check(this.get('title'), "Post title cannot be blank").notEmpty(); ghostBookshelf.validator.check(this.get('title'), "Post title cannot be blank").notEmpty();
return true; return true;
}, },
@ -61,7 +61,7 @@ Post = GhostBookshelf.Model.extend({
this.set('published_by', 1); this.set('published_by', 1);
} }
GhostBookshelf.Model.prototype.saving.call(this); ghostBookshelf.Model.prototype.saving.call(this);
if (this.hasChanged('slug')) { if (this.hasChanged('slug')) {
// Pass the new slug through the generator to strip illegal characters, detect duplicates // Pass the new slug through the generator to strip illegal characters, detect duplicates
@ -80,7 +80,7 @@ Post = GhostBookshelf.Model.extend({
this.set('author_id', 1); this.set('author_id', 1);
} }
GhostBookshelf.Model.prototype.creating.call(this); ghostBookshelf.Model.prototype.creating.call(this);
if (!this.get('slug')) { if (!this.get('slug')) {
// Generating a slug requires a db call to look for conflicting slugs // Generating a slug requires a db call to look for conflicting slugs
@ -174,7 +174,7 @@ Post = GhostBookshelf.Model.extend({
findAll: function (options) { findAll: function (options) {
options = options || {}; options = options || {};
options.withRelated = [ 'author', 'user', 'tags' ]; options.withRelated = [ 'author', 'user', 'tags' ];
return GhostBookshelf.Model.findAll.call(this, options); return ghostBookshelf.Model.findAll.call(this, options);
}, },
// #### findOne // #### findOne
@ -182,7 +182,7 @@ Post = GhostBookshelf.Model.extend({
findOne: function (args, options) { findOne: function (args, options) {
options = options || {}; options = options || {};
options.withRelated = [ 'author', 'user', 'tags' ]; options.withRelated = [ 'author', 'user', 'tags' ];
return GhostBookshelf.Model.findOne.call(this, args, options); return ghostBookshelf.Model.findOne.call(this, args, options);
}, },
// #### findPage // #### findPage
@ -251,7 +251,7 @@ Post = GhostBookshelf.Model.extend({
// After we're done, we need to figure out what // After we're done, we need to figure out what
// the limits are for the pagination values. // the limits are for the pagination values.
qb = GhostBookshelf.Knex(_.result(collection, 'tableName')); qb = ghostBookshelf.knex(_.result(collection, 'tableName'));
if (opts.where) { if (opts.where) {
qb.where(opts.where); qb.where(opts.where);
@ -328,7 +328,7 @@ Post = GhostBookshelf.Model.extend({
}, },
add: function (newPostData, options) { add: function (newPostData, options) {
return GhostBookshelf.Model.add.call(this, newPostData, options).tap(function (post) { return ghostBookshelf.Model.add.call(this, newPostData, options).tap(function (post) {
// associated models can't be created until the post has an ID, so run this after // associated models can't be created until the post has an ID, so run this after
return post.updateTags(newPostData.tags); return post.updateTags(newPostData.tags);
}); });
@ -349,7 +349,7 @@ Post = GhostBookshelf.Model.extend({
}); });
Posts = GhostBookshelf.Collection.extend({ Posts = ghostBookshelf.Collection.extend({
model: Post model: Post

View File

@ -1,18 +1,18 @@
var User = require('./user').User, var User = require('./user').User,
Permission = require('./permission').Permission, Permission = require('./permission').Permission,
GhostBookshelf = require('./base'), ghostBookshelf = require('./base'),
Role, Role,
Roles; Roles;
Role = GhostBookshelf.Model.extend({ Role = ghostBookshelf.Model.extend({
tableName: 'roles', tableName: 'roles',
permittedAttributes: ['id', 'uuid', 'name', 'description', 'created_at', 'created_by', 'updated_at', 'updated_by'], permittedAttributes: ['id', 'uuid', 'name', 'description', 'created_at', 'created_by', 'updated_at', 'updated_by'],
validate: function () { validate: function () {
GhostBookshelf.validator.check(this.get('name'), "Role name cannot be blank").notEmpty(); ghostBookshelf.validator.check(this.get('name'), "Role name cannot be blank").notEmpty();
GhostBookshelf.validator.check(this.get('description'), "Role description cannot be blank").notEmpty(); ghostBookshelf.validator.check(this.get('description'), "Role description cannot be blank").notEmpty();
}, },
users: function () { users: function () {
@ -24,7 +24,7 @@ Role = GhostBookshelf.Model.extend({
} }
}); });
Roles = GhostBookshelf.Collection.extend({ Roles = ghostBookshelf.Collection.extend({
model: Role model: Role
}); });

View File

@ -1,6 +1,6 @@
var Settings, var Settings,
GhostBookshelf = require('./base'), ghostBookshelf = require('./base'),
validator = GhostBookshelf.validator, validator = ghostBookshelf.validator,
uuid = require('node-uuid'), uuid = require('node-uuid'),
_ = require('underscore'), _ = require('underscore'),
errors = require('../errorHandling'), errors = require('../errorHandling'),
@ -29,7 +29,7 @@ defaultSettings = parseDefaultSettings();
// Each setting is saved as a separate row in the database, // Each setting is saved as a separate row in the database,
// but the overlying API treats them as a single key:value mapping // but the overlying API treats them as a single key:value mapping
Settings = GhostBookshelf.Model.extend({ Settings = ghostBookshelf.Model.extend({
tableName: 'settings', tableName: 'settings',
@ -83,7 +83,7 @@ Settings = GhostBookshelf.Model.extend({
this.set('value', this.sanitize('value')); this.set('value', this.sanitize('value'));
} }
return GhostBookshelf.Model.prototype.saving.apply(this, arguments); return ghostBookshelf.Model.prototype.saving.apply(this, arguments);
} }
}, { }, {
@ -92,7 +92,7 @@ Settings = GhostBookshelf.Model.extend({
if (!_.isObject(_key)) { if (!_.isObject(_key)) {
_key = { key: _key }; _key = { key: _key };
} }
return GhostBookshelf.Model.read.call(this, _key); return ghostBookshelf.Model.read.call(this, _key);
}, },
edit: function (_data) { edit: function (_data) {

View File

@ -1,9 +1,9 @@
var Tag, var Tag,
Tags, Tags,
Posts = require('./post').Posts, Posts = require('./post').Posts,
GhostBookshelf = require('./base'); ghostBookshelf = require('./base');
Tag = GhostBookshelf.Model.extend({ Tag = ghostBookshelf.Model.extend({
tableName: 'tags', tableName: 'tags',
@ -20,7 +20,7 @@ Tag = GhostBookshelf.Model.extend({
creating: function () { creating: function () {
var self = this; var self = this;
GhostBookshelf.Model.prototype.creating.call(this); ghostBookshelf.Model.prototype.creating.call(this);
if (!this.get('slug')) { if (!this.get('slug')) {
// Generating a slug requires a db call to look for conflicting slugs // Generating a slug requires a db call to look for conflicting slugs
@ -36,7 +36,7 @@ Tag = GhostBookshelf.Model.extend({
} }
}); });
Tags = GhostBookshelf.Collection.extend({ Tags = ghostBookshelf.Collection.extend({
model: Tag model: Tag

View File

@ -7,14 +7,14 @@ var User,
nodefn = require('when/node/function'), nodefn = require('when/node/function'),
bcrypt = require('bcrypt-nodejs'), bcrypt = require('bcrypt-nodejs'),
Posts = require('./post').Posts, Posts = require('./post').Posts,
GhostBookshelf = require('./base'), ghostBookshelf = require('./base'),
Role = require('./role').Role, Role = require('./role').Role,
Permission = require('./permission').Permission; Permission = require('./permission').Permission;
function validatePasswordLength(password) { function validatePasswordLength(password) {
try { try {
GhostBookshelf.validator.check(password, "Your must be at least 8 characters long.").len(8); ghostBookshelf.validator.check(password, "Your must be at least 8 characters long.").len(8);
} catch (error) { } catch (error) {
return when.reject(error); return when.reject(error);
} }
@ -22,7 +22,7 @@ function validatePasswordLength(password) {
return when.resolve(); return when.resolve();
} }
User = GhostBookshelf.Model.extend({ User = ghostBookshelf.Model.extend({
tableName: 'users', tableName: 'users',
@ -33,10 +33,10 @@ User = GhostBookshelf.Model.extend({
], ],
validate: function () { validate: function () {
GhostBookshelf.validator.check(this.get('email'), "Please enter a valid email address. That one looks a bit dodgy.").isEmail(); ghostBookshelf.validator.check(this.get('email'), "Please enter a valid email address. That one looks a bit dodgy.").isEmail();
GhostBookshelf.validator.check(this.get('bio'), "We're not writing a novel here! I'm afraid your bio has to stay under 200 characters.").len(0, 200); ghostBookshelf.validator.check(this.get('bio'), "We're not writing a novel here! I'm afraid your bio has to stay under 200 characters.").len(0, 200);
if (this.get('website') && this.get('website').length > 0) { if (this.get('website') && this.get('website').length > 0) {
GhostBookshelf.validator.check(this.get('website'), "Looks like your website is not actually a website. Try again?").isUrl(); ghostBookshelf.validator.check(this.get('website'), "Looks like your website is not actually a website. Try again?").isUrl();
} }
return true; return true;
}, },
@ -44,7 +44,7 @@ User = GhostBookshelf.Model.extend({
creating: function () { creating: function () {
var self = this; var self = this;
GhostBookshelf.Model.prototype.creating.call(this); ghostBookshelf.Model.prototype.creating.call(this);
if (!this.get('slug')) { if (!this.get('slug')) {
// Generating a slug requires a db call to look for conflicting slugs // Generating a slug requires a db call to look for conflicting slugs
@ -63,7 +63,7 @@ User = GhostBookshelf.Model.extend({
this.set('website', this.sanitize('website')); this.set('website', this.sanitize('website'));
this.set('bio', this.sanitize('bio')); this.set('bio', this.sanitize('bio'));
return GhostBookshelf.Model.prototype.saving.apply(this, arguments); return ghostBookshelf.Model.prototype.saving.apply(this, arguments);
}, },
posts: function () { posts: function () {
@ -111,7 +111,7 @@ User = GhostBookshelf.Model.extend({
// Assign the hashed password // Assign the hashed password
userData.password = hash; userData.password = hash;
// Save the user with the hashed password // Save the user with the hashed password
return GhostBookshelf.Model.add.call(self, userData); return ghostBookshelf.Model.add.call(self, userData);
}).then(function (addedUser) { }).then(function (addedUser) {
// Assign the userData to our created user so we can pass it back // Assign the userData to our created user so we can pass it back
userData = addedUser; userData = addedUser;
@ -135,8 +135,8 @@ User = GhostBookshelf.Model.extend({
// } // }
// return nodefn.call(bcrypt.hash, _user.password, null, null).then(function (hash) { // return nodefn.call(bcrypt.hash, _user.password, null, null).then(function (hash) {
// userData.password = hash; // userData.password = hash;
// GhostBookshelf.Model.add.call(UserRole, userRoles); // ghostBookshelf.Model.add.call(UserRole, userRoles);
// return GhostBookshelf.Model.add.call(User, userData); // return ghostBookshelf.Model.add.call(User, userData);
// }, errors.logAndThrowError); // }, errors.logAndThrowError);
// }, errors.logAndThrowError); // }, errors.logAndThrowError);
@ -239,7 +239,7 @@ User = GhostBookshelf.Model.extend({
}); });
Users = GhostBookshelf.Collection.extend({ Users = ghostBookshelf.Collection.extend({
model: User model: User
}); });

View File

@ -5,7 +5,7 @@ var testUtils = require('./testUtils'),
// Stuff we are testing // Stuff we are testing
Models = require('../../server/models'), Models = require('../../server/models'),
knex = require('../../server/models/base').Knex; knex = require('../../server/models/base').knex;
describe('Settings Model', function () { describe('Settings Model', function () {

View File

@ -7,7 +7,7 @@ var testUtils = require('./testUtils'),
errors = require('../../server/errorHandling'), errors = require('../../server/errorHandling'),
// Stuff we are testing // Stuff we are testing
knex = require("../../server/models/base").Knex, knex = require("../../server/models/base").knex,
migration = require('../../server/data/migration'), migration = require('../../server/data/migration'),
exporter = require('../../server/data/export'), exporter = require('../../server/data/export'),
importer = require('../../server/data/import'), importer = require('../../server/data/import'),

View File

@ -1,4 +1,4 @@
var knex = require('../../server/models/base').Knex, var knex = require('../../server/models/base').knex,
when = require('when'), when = require('when'),
migration = require("../../server/data/migration/"), migration = require("../../server/data/migration/"),
Settings = require('../../server/models/settings').Settings, Settings = require('../../server/models/settings').Settings,

View File

@ -19,8 +19,8 @@
"underscore": "1.5.1", "underscore": "1.5.1",
"showdown": "0.3.1", "showdown": "0.3.1",
"sqlite3": "2.1.16", "sqlite3": "2.1.16",
"bookshelf": "0.3.1", "bookshelf": "0.5.7",
"knex": "0.2.7-alpha", "knex": "0.4.11",
"when": "2.2.1", "when": "2.2.1",
"bcrypt-nodejs": "0.0.3", "bcrypt-nodejs": "0.0.3",
"node-uuid": "1.4.0", "node-uuid": "1.4.0",