diff --git a/README.md b/README.md index 787ca81..9662ab5 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ `deferred-leveldown` implements the basic [abstract-leveldown](https://github.com/Level/abstract-leveldown) API so it can be used as a drop-in replacement where `leveldown` is needed. -`put()`, `get()`, `del()` and `batch()` operations are all queued and kept in memory until the `abstract-leveldown`-compatible object has been opened through `deferred-leveldown`'s `open()` method. +`put()`, `get()`, `del()`, `batch()` and `clear()` operations are all queued and kept in memory until the `abstract-leveldown`-compatible object has been opened through `deferred-leveldown`'s `open()` method. `batch()` operations will all be replayed as the array form. Chained-batch operations are converted before being stored. diff --git a/deferred-leveldown.js b/deferred-leveldown.js index 3fc83d7..6bb1db7 100644 --- a/deferred-leveldown.js +++ b/deferred-leveldown.js @@ -1,7 +1,8 @@ var AbstractLevelDOWN = require('abstract-leveldown').AbstractLevelDOWN var inherits = require('inherits') var DeferredIterator = require('./deferred-iterator') -var deferrables = 'put get del batch'.split(' ') +var deferrables = 'put get del batch clear'.split(' ') +var optionalDeferrables = 'approximateSize compactRange'.split(' ') function DeferredLevelDOWN (db) { AbstractLevelDOWN.call(this, '') @@ -48,11 +49,13 @@ function open (self) { return this._db[m].apply(this._db, arguments) } }) - if (self._db.approximateSize) { - self.approximateSize = function () { - return this._db.approximateSize.apply(this._db, arguments) + optionalDeferrables.forEach(function (m) { + if (typeof self._db[m] === 'function') { + self[m] = function () { + return this._db[m].apply(this._db, arguments) + } } - } + }) } function closed (self) { @@ -61,14 +64,13 @@ function closed (self) { this._operations.push({ method: m, args: arguments }) } }) - if (typeof self._db.approximateSize === 'function') { - self.approximateSize = function () { - this._operations.push({ - method: 'approximateSize', - args: arguments - }) + optionalDeferrables.forEach(function (m) { + if (typeof self._db[m] === 'function') { + self[m] = function () { + this._operations.push({ method: m, args: arguments }) + } } - } + }) self._iterator = function (options) { var it = new DeferredIterator(options) this._iterators.push(it) diff --git a/package.json b/package.json index e80e9b8..1f3158d 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "prepublishOnly": "npm run dependency-check" }, "dependencies": { - "abstract-leveldown": "~6.0.0", + "abstract-leveldown": "~6.1.0", "inherits": "^2.0.3" }, "devDependencies": { diff --git a/test.js b/test.js index df64752..6b0ce7f 100644 --- a/test.js +++ b/test.js @@ -90,6 +90,15 @@ test('many operations', function (t) { } callback() }, + clear: function (options, callback) { + if (clears++ === 0) { + t.deepEqual(options, { reverse: false, limit: -1 }, 'default options') + } else { + t.deepEqual(options, { gt: 'k5', reverse: false, limit: -1 }, 'range option') + } + + callback() + }, open: function (options, callback) { process.nextTick(callback) } @@ -99,6 +108,7 @@ test('many operations', function (t) { var puts = 0 var gets = 0 var batches = 0 + var clears = 0 ld.put('foo1', 'bar1', function (err, v) { t.error(err, 'no error') @@ -108,6 +118,9 @@ test('many operations', function (t) { t.error(err, 'no error') calls.push({ type: 'get', key: 'woo1', v: v }) }) + ld.clear(function () { + calls.push({ type: 'clear' }) + }) ld.put('foo2', 'bar2', function (err, v) { t.error(err, 'no error') calls.push({ type: 'put', key: 'foo2', v: v }) @@ -133,21 +146,26 @@ test('many operations', function (t) { .write(function () { calls.push({ type: 'batch', keys: 'k3,k4' }) }) + ld.clear({ gt: 'k5' }, function () { + calls.push({ type: 'clear', gt: 'k5' }) + }) t.ok(calls.length === 0, 'not called') ld.open(function (err) { t.error(err, 'no error') - t.equal(calls.length, 7, 'all functions called') + t.equal(calls.length, 9, 'all functions called') t.deepEqual(calls, [ { type: 'put', key: 'foo1', v: 'put1' }, { type: 'get', key: 'woo1', v: 'gets1' }, + { type: 'clear' }, { type: 'put', key: 'foo2', v: 'put2' }, { type: 'get', key: 'woo2', v: 'gets2' }, { type: 'del', key: 'blergh', v: 'del' }, { type: 'batch', keys: 'k1,k2' }, - { type: 'batch', keys: 'k3,k4' } + { type: 'batch', keys: 'k3,k4' }, + { type: 'clear', gt: 'k5' } ], 'calls correctly behaved') t.end() @@ -183,7 +201,7 @@ test('keys and values should not be serialized', function (t) { function noop () {} - t.plan(5) + t.plan(8) t.test('put', function (t) { var calls = [] @@ -220,6 +238,19 @@ test('keys and values should not be serialized', function (t) { }) }) + t.test('clear', function (t) { + var calls = [] + var ld = Db('clear', function (opts, cb) { calls.push(opts) }) + ITEMS.forEach(function (key) { ld.clear({ gt: key }, noop) }) + ld.open(function (err) { + t.error(err, 'no error') + t.same(calls, ITEMS.map(function (key) { + return { gt: key, reverse: false, limit: -1 } + }), 'value ok') + t.end() + }) + }) + t.test('approximateSize', function (t) { var calls = [] var ld = Db('approximateSize', function (start, end, cb) { @@ -242,6 +273,29 @@ test('keys and values should not be serialized', function (t) { }, /approximateSize is not a function/) t.end() }) + + t.test('compactRange', function (t) { + var calls = [] + var ld = Db('compactRange', function (start, end, cb) { + calls.push({ start: start, end: end }) + }) + ITEMS.forEach(function (key) { ld.compactRange(key, key, noop) }) + ld.open(function (err) { + t.error(err, 'no error') + t.same(calls, ITEMS.map(function (i) { + return { start: i, end: i } + }), 'value ok') + t.end() + }) + }) + + t.test('store not supporting compactRange', function (t) { + var ld = Db('FOO', function () {}) + t.throws(function () { + ld.compactRange('key', 'key', noop) + }, /compactRange is not a function/) + t.end() + }) }) test('_close calls close for underlying store', function (t) { @@ -315,6 +369,29 @@ test('non-deferred approximateSize', function (t) { }) }) +test('non-deferred compactRange', function (t) { + t.plan(4) + + var db = { + open: function (options, cb) { + process.nextTick(cb) + }, + compactRange: function (start, end, callback) { + t.is(start, 'bar') + t.is(end, 'foo') + process.nextTick(callback) + } + } + var ld = new DeferredLevelDOWN(db) + + ld.open(function (err) { + t.error(err) + ld.compactRange('bar', 'foo', function (err) { + t.error(err) + }) + }) +}) + test('iterator - deferred operations', function (t) { t.plan(9)