diff --git a/.travis.yml b/.travis.yml index b0ed593b..62167c88 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: node_js node_js: - - 6 + - 10 cache: directories: diff --git a/lib/datastore.js b/lib/datastore.js index 46973149..861843cb 100755 --- a/lib/datastore.js +++ b/lib/datastore.js @@ -3,6 +3,7 @@ var customUtils = require('./custom-utils') , async = require('async') , Executor = require('./executor') , Index = require('./indexes') + , util = require('util') , _ = require('underscore') , Persistence = require('./persistence') , Cursor = require('./cursor') @@ -82,6 +83,7 @@ function Datastore (options) { }); } } +util.inherits(Datastore, require('events').EventEmitter); /** * Load the database from the datafile, and trigger the execution of buffered commands if any diff --git a/lib/persistence.js b/lib/persistence.js index 1ca7684e..1fac2f3f 100755 --- a/lib/persistence.js +++ b/lib/persistence.js @@ -73,7 +73,13 @@ Persistence.prototype.ensureDirectoryExists = function (dir, cb) { var callback = cb || function () {} ; - this.storage.mkdirp(dir, function (err) { return callback(err); }); + this.storage.mkdirp(dir) + .then(function (made) { + return callback(); + }) + .catch(function (error) { + return callback(error); + }); }; diff --git a/package.json b/package.json index a2d44a1d..c4804ec8 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nedb-core", - "version": "3.0.6", + "version": "3.0.7", "author": { "name": "Louis Chatriot", "email": "louis.chatriot@gmail.com" @@ -21,11 +21,11 @@ "url": "git@github.com:nedb3/nedb3.git" }, "dependencies": { - "async": "latest", - "is": "latest", - "localforage": "latest", - "mkdirp": "latest", - "underscore": "latest" + "async": "^3.2.0", + "is": "^3.3.0", + "localforage": "^1.7.3", + "mkdirp": "^1.0.3", + "underscore": "^1.12.1" }, "devDependencies": { "chai": "latest", diff --git a/test/db.test.js b/test/db.test.js index 5e72cab0..099b985d 100755 --- a/test/db.test.js +++ b/test/db.test.js @@ -393,17 +393,38 @@ describe('Database', function () { it('If the callback throws an uncaught exception, do not catch it inside findOne, this is userspace concern', function (done) { var tryCount = 0 , currentUncaughtExceptionHandlers = process.listeners('uncaughtException') + , currentUnhandledRejectionHandlers = process.listeners('unhandledRejection') , i ; process.removeAllListeners('uncaughtException'); + process.removeAllListeners('unhandledRejection'); + + process.on('unhandledRejection', function (ex) { + process.removeAllListeners('uncaughtException'); + process.removeAllListeners('unhandledRejection'); + + for (i = 0; i < currentUncaughtExceptionHandlers.length; i += 1) { + process.on('uncaughtException', currentUncaughtExceptionHandlers[i]); + } + for (i = 0; i < currentUnhandledRejectionHandlers.length; i += 1) { + process.on('unhandledRejection', currentUnhandledRejectionHandlers[i]); + } + + ex.message.should.equal('SOME EXCEPTION'); + done(); + }); process.on('uncaughtException', function MINE (ex) { process.removeAllListeners('uncaughtException'); + process.removeAllListeners('unhandledRejection'); for (i = 0; i < currentUncaughtExceptionHandlers.length; i += 1) { process.on('uncaughtException', currentUncaughtExceptionHandlers[i]); } + for (i = 0; i < currentUnhandledRejectionHandlers.length; i += 1) { + process.on('unhandledRejection', currentUnhandledRejectionHandlers[i]); + } ex.message.should.equal('SOME EXCEPTION'); done(); @@ -828,7 +849,7 @@ describe('Database', function () { }); }); }); - + it('Can use sort, skip and limit if the callback is not passed to find but to exec', function (done) { d.insert({ a: 2, hello: 'world' }, function () { d.insert({ a: 24, hello: 'earth' }, function () { @@ -843,7 +864,7 @@ describe('Database', function () { }); }); }); - }); + }); }); }); @@ -856,7 +877,7 @@ describe('Database', function () { d.findOne({}).sort({ a: 1 }).exec(function (err, doc) { assert.isNull(err); doc.hello.should.equal('world'); - + // A query d.findOne({ a: { $gt: 14 } }).sort({ a: 1 }).exec(function (err, doc) { assert.isNull(err); @@ -1230,13 +1251,13 @@ describe('Database', function () { d.find({}, function (err, docs) { docs.length.should.equal(1); // Default option for upsert is false docs[0].something.should.equal("created ok"); - + // Modifying the returned upserted document doesn't modify the database newDoc.newField = true; d.find({}, function (err, docs) { docs[0].something.should.equal("created ok"); assert.isUndefined(docs[0].newField); - + done(); }); }); @@ -1244,7 +1265,7 @@ describe('Database', function () { }); }); }); - + it('If the update query is a normal object with no modifiers, it is the doc that will be upserted', function (done) { d.update({ $or: [{ a: 4 }, { a: 5 }] }, { hello: 'world', bloup: 'blap' }, { upsert: true }, function (err) { d.find({}, function (err, docs) { @@ -1258,7 +1279,7 @@ describe('Database', function () { }); }); }); - + it('If the update query contains modifiers, it is applied to the object resulting from removing all operators from the find query 1', function (done) { d.update({ $or: [{ a: 4 }, { a: 5 }] }, { $set: { hello: 'world' }, $inc: { bloup: 3 } }, { upsert: true }, function (err) { d.find({ hello: 'world' }, function (err, docs) { @@ -1272,7 +1293,7 @@ describe('Database', function () { }); }); }); - + it('If the update query contains modifiers, it is applied to the object resulting from removing all operators from the find query 2', function (done) { d.update({ $or: [{ a: 4 }, { a: 5 }], cac: 'rrr' }, { $set: { hello: 'world' }, $inc: { bloup: 3 } }, { upsert: true }, function (err) { d.find({ hello: 'world' }, function (err, docs) { @@ -1287,7 +1308,7 @@ describe('Database', function () { }); }); }); - + it('Performing upsert with badly formatted fields yields a standard error not an exception', function(done) { d.update({_id: '1234'}, { $set: { $$badfield: 5 }}, { upsert: true }, function(err, doc) { assert.isDefined(err); @@ -1504,7 +1525,7 @@ describe('Database', function () { }); }); }); - + it('Can update without the options arg (will use defaults then)', function (done) { d.insert({ a:1, hello: 'world' }, function (err, doc1) { d.insert({ a:2, hello: 'earth' }, function (err, doc2) { @@ -1517,11 +1538,11 @@ describe('Database', function () { , d2 = _.find(docs, function (doc) { return doc._id === doc2._id }) , d3 = _.find(docs, function (doc) { return doc._id === doc3._id }) ; - + d1.a.should.equal(1); d2.a.should.equal(12); d3.a.should.equal(5); - + done(); }); }); @@ -1875,7 +1896,7 @@ describe('Database', function () { }); }); }); - + it('Can remove without the options arg (will use defaults then)', function (done) { d.insert({ a:1, hello: 'world' }, function (err, doc1) { d.insert({ a:2, hello: 'earth' }, function (err, doc2) { @@ -1888,11 +1909,11 @@ describe('Database', function () { , d2 = _.find(docs, function (doc) { return doc._id === doc2._id }) , d3 = _.find(docs, function (doc) { return doc._id === doc3._id }) ; - + d1.a.should.equal(1); assert.isUndefined(d2); d3.a.should.equal(5); - + done(); }); }); @@ -1936,33 +1957,33 @@ describe('Database', function () { }); }); }); - + it('ensureIndex can be called twice on the same field, the second call will ahve no effect', function (done) { Object.keys(d.indexes).length.should.equal(1); Object.keys(d.indexes)[0].should.equal("_id"); - + d.insert({ planet: "Earth" }, function () { d.insert({ planet: "Mars" }, function () { d.find({}, function (err, docs) { docs.length.should.equal(2); - + d.ensureIndex({ fieldName: "planet" }, function (err) { assert.isNull(err); Object.keys(d.indexes).length.should.equal(2); - Object.keys(d.indexes)[0].should.equal("_id"); - Object.keys(d.indexes)[1].should.equal("planet"); + Object.keys(d.indexes)[0].should.equal("_id"); + Object.keys(d.indexes)[1].should.equal("planet"); d.indexes.planet.getAll().length.should.equal(2); - + // This second call has no effect, documents don't get inserted twice in the index d.ensureIndex({ fieldName: "planet" }, function (err) { assert.isNull(err); Object.keys(d.indexes).length.should.equal(2); - Object.keys(d.indexes)[0].should.equal("_id"); - Object.keys(d.indexes)[1].should.equal("planet"); + Object.keys(d.indexes)[0].should.equal("_id"); + Object.keys(d.indexes)[1].should.equal("planet"); + + d.indexes.planet.getAll().length.should.equal(2); - d.indexes.planet.getAll().length.should.equal(2); - done(); }); }); @@ -2141,19 +2162,19 @@ describe('Database', function () { }); }); }); - + it('Can remove an index', function (done) { d.ensureIndex({ fieldName: 'e' }, function (err) { assert.isNull(err); - + Object.keys(d.indexes).length.should.equal(2); assert.isNotNull(d.indexes.e); - + d.removeIndex("e", function (err) { assert.isNull(err); Object.keys(d.indexes).length.should.equal(1); - assert.isUndefined(d.indexes.e); - + assert.isUndefined(d.indexes.e); + done(); }); }); @@ -2161,7 +2182,7 @@ describe('Database', function () { }); // ==== End of 'ensureIndex and index initialization in database loading' ==== // - + describe('Indexing newly inserted documents', function () { it('Newly inserted documents are indexed', function (done) { @@ -2815,7 +2836,7 @@ describe('Database', function () { assert.isNull(err); Object.keys(db.indexes).length.should.equal(3); Object.keys(db.indexes)[0].should.equal("_id"); - Object.keys(db.indexes)[1].should.equal("planet"); + Object.keys(db.indexes)[1].should.equal("planet"); Object.keys(db.indexes)[2].should.equal("another"); db.indexes._id.getAll().length.should.equal(2); db.indexes.planet.getAll().length.should.equal(2); diff --git a/test_lac/loadAndCrash.test.js b/test_lac/loadAndCrash.test.js index cbe9bc3b..28dfbb95 100755 --- a/test_lac/loadAndCrash.test.js +++ b/test_lac/loadAndCrash.test.js @@ -104,7 +104,7 @@ fs.writeFile = function(path, data, options, callback_) { }); function writeFd(fd, isUserFd) { - var buffer = (data instanceof Buffer) ? data : new Buffer('' + data, + var buffer = (data instanceof Buffer) ? data : Buffer.from('' + data, options.encoding || 'utf8'); var position = /a/.test(flag) ? null : 0;