diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..43c97e7 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/.travis.yml b/.travis.yml index 1d0ad98..c60f507 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,6 @@ sudo: false language: node_js node_js: - - "4" - "6" + - "8" + - "10" diff --git a/lib/sql.js b/lib/sql.js index 20790ed..46e71c3 100644 --- a/lib/sql.js +++ b/lib/sql.js @@ -167,7 +167,7 @@ SQLConnector.prototype.addPropertyToActual = function(model, propName) { var sqlCommand = self.columnEscaped(model, propName) + ' ' + self.columnDataType(model, propName) + (self.isNullable(self.getPropertyDefinition(model, propName)) ? - '' : ' NOT NULL'); + '' : ' NOT NULL'); return sqlCommand; }; @@ -631,17 +631,17 @@ SQLConnector.prototype.execute = function(sql, params, options, callback) { }; this.notifyObserversAround('execute', context, function(context, done) { self.executeSQL(context.req.sql, context.req.params, context.options, - function(err, info) { - if (err) { - debug('Error: %j %j %j', err, context.req.sql, context.req.params); - } + function(err, info) { + if (err) { + debug('Error: %j %j %j', err, context.req.sql, context.req.params); + } - if (!err && info != null) { - context.res = info; - } - // Don't pass more than one args as it will confuse async.waterfall - done(err, info); - }); + if (!err && info != null) { + context.res = info; + } + // Don't pass more than one args as it will confuse async.waterfall + done(err, info); + }); }, callback); }; @@ -816,7 +816,7 @@ SQLConnector.prototype.updateAttributes = function(model, id, data, options, cb) function errorIdNotFoundForUpdate(idValue) { var msg = g.f( - 'Could not update attributes. {{Object}} with {{id}} %s does not exist!', idValue); + 'Could not update attributes. {{Object}} with {{id}} %s does not exist!', idValue); var error = new Error(msg); error.statusCode = error.status = 404; return error; @@ -1784,8 +1784,8 @@ SQLConnector.prototype.discoverDatabaseSchemas = function(options, cb) { * @param options {all: for all owners, owner: for a given owner} * @returns {string} The sql statement */ - // Due to the different implementation structure of information_schema across - // connectors, each connector will have to generate its own query +// Due to the different implementation structure of information_schema across +// connectors, each connector will have to generate its own query SQLConnector.prototype.buildQueryTables = function(options) { throw new Error(g.f('{{buildQueryTables}} must be implemented by the connector')); }; @@ -1795,8 +1795,8 @@ SQLConnector.prototype.buildQueryTables = function(options) { * @param options {all: for all owners, owner: for a given owner} * @returns {string} The sql statement */ - // Due to the different implementation structure of information_schema across - // connectors, each connector will have to generate its own query +// Due to the different implementation structure of information_schema across +// connectors, each connector will have to generate its own query SQLConnector.prototype.buildQueryViews = function(options) { throw new Error(g.f('{{buildQueryViews}} must be implemented by the connector')); }; @@ -1946,8 +1946,8 @@ SQLConnector.prototype.discoverPrimaryKeys = function(table, options, cb) { * @param table * @returns {string} */ - // Due to the different implementation structure of information_schema across - // connectors, each connector will have to generate its own query +// Due to the different implementation structure of information_schema across +// connectors, each connector will have to generate its own query SQLConnector.prototype.buildQueryForeignKeys = function(schema, table) { throw new Error(g.f('{{buildQueryForeignKeys}} must be implemented by the connector')); }; @@ -1982,8 +1982,8 @@ SQLConnector.prototype.discoverForeignKeys = function(table, options, cb) { * @param table * @returns {string} */ - // Due to the different implementation structure of information_schema across - // connectors, each connector will have to generate its own query +// Due to the different implementation structure of information_schema across +// connectors, each connector will have to generate its own query SQLConnector.prototype.buildQueryExportedForeignKeys = function(schema, table) { throw new Error(g.f('{{buildQueryExportedForeignKeys}} must be implemented by' + 'the connector')); diff --git a/package.json b/package.json index 526ce04..89fa25c 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "4.4.0", "description": "Building blocks for LoopBack connectors", "engines": { - "node": ">=4" + "node": ">=6" }, "keywords": [ "StrongLoop", @@ -25,15 +25,15 @@ "async": "^2.1.5", "bluebird": "^3.4.6", "debug": "^3.1.0", - "msgpack5": "^3.4.1", - "strong-globalize": "^3.1.0", + "msgpack5": "^4.2.0", + "strong-globalize": "^4.1.1", "uuid": "^3.0.1" }, "devDependencies": { - "chai": "~3.5.0", - "eslint": "^3.17.1", - "eslint-config-loopback": "^8.0.0", + "chai": "^4.1.2", + "eslint": "^4.19.1", + "eslint-config-loopback": "^10.0.0", "loopback-datasource-juggler": "^3.12.0", - "mocha": "^3.2.0" + "mocha": "^5.2.0" } } diff --git a/test/transaction.test.js b/test/transaction.test.js index 3e254dc..9ce4d88 100644 --- a/test/transaction.test.js +++ b/test/transaction.test.js @@ -41,42 +41,42 @@ describe('transactions', function() { isolationLevel: Transaction.READ_COMMITTED, timeout: timeout, }, - function(err, tx) { - if (err) return done(err); - expect(typeof tx.id).to.eql('string'); - hooks = []; - tx.observe('before commit', function(context, next) { - hooks.push('before commit'); - next(); - }); - tx.observe('after commit', function(context, next) { - hooks.push('after commit'); - next(); - }); - tx.observe('before rollback', function(context, next) { - hooks.push('before rollback'); - next(); - }); - tx.observe('after rollback', function(context, next) { - hooks.push('after rollback'); - next(); - }); - currentTx = tx; - Post.create(post, {transaction: tx, model: 'Post'}, - function(err, p) { - if (err) { - done(err); - } else { - p.reviews.create({ - author: 'John', - content: 'Review for ' + p.title, - }, {transaction: tx, model: 'Review'}, - function(err, c) { - done(err); - }); - } - }); + function(err, tx) { + if (err) return done(err); + expect(typeof tx.id).to.eql('string'); + hooks = []; + tx.observe('before commit', function(context, next) { + hooks.push('before commit'); + next(); }); + tx.observe('after commit', function(context, next) { + hooks.push('after commit'); + next(); + }); + tx.observe('before rollback', function(context, next) { + hooks.push('before rollback'); + next(); + }); + tx.observe('after rollback', function(context, next) { + hooks.push('after rollback'); + next(); + }); + currentTx = tx; + Post.create(post, {transaction: tx, model: 'Post'}, + function(err, p) { + if (err) { + done(err); + } else { + p.reviews.create({ + author: 'John', + content: 'Review for ' + p.title, + }, {transaction: tx, model: 'Review'}, + function(err, c) { + done(err); + }); + } + }); + }); }; } @@ -173,24 +173,26 @@ describe('transactions', function() { }); describe('timeout', function() { + const TIMEOUT = 50; before(function() { // Reset the collection db.connector.data = {}; }); var post = {title: 't3', content: 'c3'}; - before(createPostInTx(post, 50)); + beforeEach(createPostInTx(post, TIMEOUT)); it('should report timeout', function(done) { - setTimeout(function() { + // wait until the "create post" transaction times out + setTimeout(runTheTest, TIMEOUT * 3); + + function runTheTest() { Post.find({where: {title: 't3'}}, {transaction: currentTx}, function(err, posts) { - if (err) return done(err); - expect(posts.length).to.be.eql(1); + expect(err).to.match(/transaction.*not active/); done(); }); - }, 300); - done(); + } }); it('should invoke the timeout hook', function(done) { @@ -198,6 +200,10 @@ describe('transactions', function() { next(); done(); }); + + // If the event is not fired quickly enough, then the test can + // quickly fail - no need to wait full two seconds (Mocha's default) + this.timeout(TIMEOUT * 3); }); });