Skip to content
This repository was archived by the owner on Dec 20, 2024. It is now read-only.

Commit 3074af8

Browse files
committed
Support promises and abstract-level
1 parent 7cad6e0 commit 3074af8

File tree

5 files changed

+127
-21
lines changed

5 files changed

+127
-21
lines changed

README.md

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# level-concat-iterator
22

3-
> Concatenate items from an iterator into an array.
3+
> Concatenate entries from an iterator into an array.
44
55
[![level badge][level-badge]](https://github.com/Level/awesome)
66
[![npm](https://img.shields.io/npm/v/level-concat-iterator.svg?label=&logo=npm)](https://www.npmjs.com/package/level-concat-iterator)
@@ -23,21 +23,29 @@ const db = level('./db')
2323
db.put('foo', 'bar', function (err) {
2424
if (err) throw err
2525

26-
concat(db.iterator(), function (err, data) {
26+
concat(db.iterator(), function (err, entries) {
2727
if (err) throw err
2828

29-
console.log(data)
29+
// [{ key: 'foo', value: 'bar' }]
30+
console.log(entries)
3031
})
3132
})
3233
```
3334

35+
With promises:
36+
37+
```js
38+
await db.put('foo', 'bar')
39+
const entries = await concat(db.iterator())
40+
```
41+
3442
**If you are upgrading:** please see [`UPGRADING.md`](UPGRADING.md).
3543

3644
## API
3745

38-
### `concat(iterator, cb)`
46+
### `concat(iterator[, callback])`
3947

40-
Takes an `abstract-leveldown` compatible `iterator` as first parameter and calls back with an array of keys and values. Calls back with an error if `iterator.next(cb)` or `iterator.end(cb)` errors.
48+
Takes an `abstract-leveldown` compatible `iterator` as first parameter and calls the `callback` with an array of entries, where each entry is an object in the form `{ key, value }`. Calls the `callback` with an error if `iterator.next()` or `iterator.end()` errors. If no callback is provided, a promise is returned.
4149

4250
## Contributing
4351

example.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ const db = level('./db')
66
db.put('foo', 'bar', function (err) {
77
if (err) throw err
88

9-
concat(db.iterator(), function (err, data) {
9+
concat(db.iterator(), function (err, entries) {
1010
if (err) throw err
1111

12-
console.log(data)
12+
console.log(entries)
1313
})
1414
})

index.js

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,25 @@
11
'use strict'
22

3-
module.exports = function (iterator, cb) {
4-
const data = []
5-
const next = function () {
6-
iterator.next(function (err, key, value) {
7-
if (err || (key === undefined && value === undefined)) {
8-
return iterator.end(function (err2) {
9-
cb(err || err2, data)
10-
})
11-
}
12-
data.push({ key, value })
13-
next()
14-
})
3+
const { fromCallback } = require('catering')
4+
const kPromise = Symbol('promise')
5+
6+
module.exports = function (iterator, callback) {
7+
callback = fromCallback(callback, kPromise)
8+
9+
// Use close() method of abstract-level or end() of abstract-leveldown
10+
const close = typeof iterator.close === 'function' ? 'close' : 'end'
11+
const entries = []
12+
13+
const onnext = function (err, key, value) {
14+
if (err || (key === undefined && value === undefined)) {
15+
return iterator[close](function (err2) {
16+
callback(err || err2, entries)
17+
})
18+
}
19+
entries.push({ key, value })
20+
iterator.next(onnext)
1521
}
16-
next()
22+
23+
iterator.next(onnext)
24+
return callback[kPromise]
1725
}

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "level-concat-iterator",
33
"version": "3.0.0",
4-
"description": "Concatenate items from an iterator into an array.",
4+
"description": "Concatenate entries from an iterator into an array.",
55
"author": "Lars-Magnus Skog <ralphtheninja@riseup.net>",
66
"license": "MIT",
77
"main": "index.js",
@@ -19,6 +19,9 @@
1919
"LICENSE.md",
2020
"UPGRADING.md"
2121
],
22+
"dependencies": {
23+
"catering": "^2.1.0"
24+
},
2225
"devDependencies": {
2326
"airtap": "^4.0.3",
2427
"airtap-playwright": "^1.0.1",

test.js

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,25 @@ test('calls back with error if iterator.next errors', function (t) {
2222
})
2323
})
2424

25+
test('rejects promise if iterator.next errors', function (t) {
26+
t.plan(3)
27+
28+
const iterator = {
29+
next (cb) {
30+
t.pass('iterator.next called')
31+
process.nextTick(cb, new Error('iterator.next'))
32+
},
33+
end (cb) {
34+
t.pass('iterator.end called')
35+
process.nextTick(cb)
36+
}
37+
}
38+
39+
collect(iterator).catch(function (err) {
40+
t.is(err.message, 'iterator.next', 'correct error')
41+
})
42+
})
43+
2544
test('happy path calls back with an array', function (t) {
2645
t.plan(6)
2746

@@ -53,6 +72,34 @@ test('happy path calls back with an array', function (t) {
5372
})
5473
})
5574

75+
test('happy path resolves promise with an array', async function (t) {
76+
t.plan(5)
77+
78+
let i = 0
79+
const entries = [
80+
{ key: 'key1', value: 'value1' },
81+
{ key: 'key2', value: 'value2' }
82+
]
83+
84+
const iterator = {
85+
next (cb) {
86+
t.pass('iterator.next called')
87+
if (i < entries.length) {
88+
process.nextTick(cb, null, entries[i].key, entries[i].value)
89+
++i
90+
} else {
91+
process.nextTick(cb)
92+
}
93+
},
94+
end (cb) {
95+
t.pass('iterator.end called')
96+
process.nextTick(cb)
97+
}
98+
}
99+
100+
t.same(await collect(iterator), entries)
101+
})
102+
56103
test('calls back with error and data if iterator.end errors', function (t) {
57104
t.plan(6)
58105

@@ -84,6 +131,25 @@ test('calls back with error and data if iterator.end errors', function (t) {
84131
})
85132
})
86133

134+
test('rejects promise if iterator.end errors', function (t) {
135+
t.plan(3)
136+
137+
const iterator = {
138+
next (cb) {
139+
t.pass('iterator.next called')
140+
process.nextTick(cb)
141+
},
142+
end (cb) {
143+
t.pass('iterator.end called')
144+
process.nextTick(cb, new Error('iterator.end'))
145+
}
146+
}
147+
148+
collect(iterator).catch(function (err) {
149+
t.is(err.message, 'iterator.end', 'correct error')
150+
})
151+
})
152+
87153
test('calls back with error and partial data if iterator.end errors', function (t) {
88154
t.plan(5)
89155

@@ -114,3 +180,24 @@ test('calls back with error and partial data if iterator.end errors', function (
114180
t.same(result, [].concat(data[0]))
115181
})
116182
})
183+
184+
test('prefers iterator.close() over iterator.end()', async function (t) {
185+
t.plan(2)
186+
187+
const iterator = {
188+
next (cb) {
189+
t.pass('iterator.next called')
190+
process.nextTick(cb)
191+
},
192+
close (cb) {
193+
t.pass('iterator.close called')
194+
process.nextTick(cb)
195+
},
196+
end (cb) {
197+
t.fail('iterator.end called')
198+
process.nextTick(cb)
199+
}
200+
}
201+
202+
await collect(iterator)
203+
})

0 commit comments

Comments
 (0)