Skip to content
This repository was archived by the owner on Sep 9, 2021. It is now read-only.

Commit b2f0963

Browse files
authored
fix: remove node buffer (#43)
Swaps node Buffer for Uint8Array in keys and values. BREAKING CHANGES: - node Buffers have been replaced with Uint8Arrays - `key.toBuffer` has been replaced with `key.uint8Array()`
1 parent 0140608 commit b2f0963

File tree

8 files changed

+138
-73
lines changed

8 files changed

+138
-73
lines changed

.npmignore

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,17 @@
1+
yarn.lock
2+
package-lock.json
3+
4+
**/node_modules/
5+
**/*.log
6+
test/repo-tests*
7+
18
# Logs
29
logs
310
*.log
411

12+
coverage
13+
.nyc_output
14+
515
# Runtime data
616
pids
717
*.pid
@@ -12,19 +22,20 @@ lib-cov
1222

1323
# Coverage directory used by tools like istanbul
1424
coverage
15-
.nyc_output
1625

1726
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
1827
.grunt
1928

2029
# node-waf configuration
2130
.lock-wscript
2231

23-
# Compiled binary addons (http://nodejs.org/api/addons.html)
24-
build/Release
32+
build
2533

2634
# Dependency directory
2735
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
2836
node_modules
2937

30-
test
38+
.travis.yml
39+
.github
40+
docs
41+
test

README.md

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,13 @@
3333
- [`put(key, value, [options])` -> `Promise`](#putkey-value-options---promise)
3434
- [Arguments](#arguments-1)
3535
- [Example](#example-1)
36-
- [`putMany(source, [options])` -> `AsyncIterator<{ key: Key, value: Buffer }>`](#putmanysource-options---asynciterator-key-key-value-buffer-)
36+
- [`putMany(source, [options])` -> `AsyncIterator<{ key: Key, value: Uint8Array }>`](#putmanysource-options---asynciterator-key-key-value-uint8array-)
3737
- [Arguments](#arguments-2)
3838
- [Example](#example-2)
39-
- [`get(key, [options])` -> `Promise<Buffer>`](#getkey-options---promisebuffer)
39+
- [`get(key, [options])` -> `Promise<Uint8Array>`](#getkey-options---promiseuint8array)
4040
- [Arguments](#arguments-3)
4141
- [Example](#example-3)
42-
- [`getMany(source, [options])` -> `AsyncIterator<Buffer>`](#getmanysource-options---asynciteratorbuffer)
42+
- [`getMany(source, [options])` -> `AsyncIterator<Uint8Array>`](#getmanysource-options---asynciteratoruint8array)
4343
- [Arguments](#arguments-4)
4444
- [Example](#example-4)
4545
- [`delete(key, [options])` -> `Promise`](#deletekey-options---promise)
@@ -48,7 +48,7 @@
4848
- [`deleteMany(source, [options])` -> `AsyncIterator<Key>`](#deletemanysource-options---asynciteratorkey)
4949
- [Arguments](#arguments-6)
5050
- [Example](#example-6)
51-
- [`query(query, [options])` -> `AsyncIterable<Buffer>`](#queryquery-options---asynciterablebuffer)
51+
- [`query(query, [options])` -> `AsyncIterable<Uint8Array>`](#queryquery-options---asynciterableuint8array)
5252
- [Arguments](#arguments-7)
5353
- [Example](#example-7)
5454
- [`batch()`](#batch)
@@ -179,11 +179,11 @@ for await (const { key, data } of batch(store.putMany(source), 10)) {
179179

180180
### Keys
181181

182-
To allow a better abstraction on how to address values, there is a `Key` class which is used as identifier. It's easy to create a key from a `Buffer` or a `string`.
182+
To allow a better abstraction on how to address values, there is a `Key` class which is used as identifier. It's easy to create a key from a `Uint8Array` or a `string`.
183183

184184
```js
185185
const a = new Key('a')
186-
const b = new Key(Buffer.from('hello'))
186+
const b = new Key(new Uint8Array([0, 1, 2, 3]))
187187
```
188188

189189
The key scheme is inspired by file systems and Google App Engine key model. Keys are meant to be unique across a system. They are typically hierarchical, incorporating more and more specific namespaces. Thus keys can be deemed 'children' or 'ancestors' of other keys:
@@ -234,41 +234,41 @@ Store a value with the given key.
234234
| Name | Type | Description |
235235
| ---- | ---- | ----------- |
236236
| key | [Key][] | The key to store the value under |
237-
| value | [Buffer][] | Value to store |
237+
| value | [Uint8Array][] | Value to store |
238238
| options | [Object][] | An options object, all properties are optional |
239239
| options.signal | [AbortSignal][] | A way to signal that the caller is no longer interested in the outcome of this operation |
240240

241241
#### Example
242242

243243
```js
244-
await store.put([{ key: new Key('awesome'), value: Buffer.from('datastores') }])
244+
await store.put([{ key: new Key('awesome'), value: new Uint8Array([0, 1, 2, 3]) }])
245245
console.log('put content')
246246
```
247247

248-
### `putMany(source, [options])` -> `AsyncIterator<{ key: Key, value: Buffer }>`
248+
### `putMany(source, [options])` -> `AsyncIterator<{ key: Key, value: Uint8Array }>`
249249

250250
Store many key-value pairs.
251251

252252
#### Arguments
253253

254254
| Name | Type | Description |
255255
| ---- | ---- | ----------- |
256-
| source | [AsyncIterator][]<{ key: [Key][], value: [Buffer][] }> | The key to store the value under |
257-
| value | [Buffer][] | Value to store |
256+
| source | [AsyncIterator][]<{ key: [Key][], value: [Uint8Array][] }> | The key to store the value under |
257+
| value | [Uint8Array][] | Value to store |
258258
| options | [Object][] | An options object, all properties are optional |
259259
| options.signal | [AbortSignal][] | A way to signal that the caller is no longer interested in the outcome of this operation |
260260

261261
#### Example
262262

263263
```js
264-
const source = [{ key: new Key('awesome'), value: Buffer.from('datastores') }]
264+
const source = [{ key: new Key('awesome'), value: new Uint8Array([0, 1, 2, 3]) }]
265265

266266
for await (const { key, value } of store.putMany(source)) {
267267
console.info(`put content for key ${key}`)
268268
}
269269
```
270270

271-
### `get(key, [options])` -> `Promise<Buffer>`
271+
### `get(key, [options])` -> `Promise<Uint8Array>`
272272

273273
#### Arguments
274274

@@ -288,7 +288,7 @@ console.log('got content: %s', value.toString('utf8'))
288288
// => got content: datastore
289289
```
290290

291-
### `getMany(source, [options])` -> `AsyncIterator<Buffer>`
291+
### `getMany(source, [options])` -> `AsyncIterator<Uint8Array>`
292292

293293
#### Arguments
294294

@@ -304,7 +304,7 @@ Retrieve a stream of values stored under the given keys.
304304

305305
```js
306306
for await (const value of store.getMany([new Key('awesome')])) {
307-
console.log('got content: %s', value.toString('utf8'))
307+
console.log('got content:', new TextDecoder('utf8').decode(value))
308308
// => got content: datastore
309309
}
310310
```
@@ -350,18 +350,18 @@ for await (const key of store.deleteMany(source)) {
350350
}
351351
```
352352

353-
### `query(query, [options])` -> `AsyncIterable<Buffer>`
353+
### `query(query, [options])` -> `AsyncIterable<Uint8Array>`
354354

355-
Search the store for some values. Returns an [AsyncIterable][] with each item being a [Buffer][].
355+
Search the store for some values. Returns an [AsyncIterable][] with each item being a [Uint8Array][].
356356

357357
#### Arguments
358358

359359
| Name | Type | Description |
360360
| ---- | ---- | ----------- |
361361
| query | [Object][] | A query object, all properties are optional |
362362
| query.prefix | [String][] | Only return values where the key starts with this prefix |
363-
| query.filters | [Array][]<[Function][]([Buffer][]) -> [Boolean][]> | Filter the results according to the these functions |
364-
| query.orders | [Array][]<[Function][]([Array][]<[Buffer][]>) -> [Array][]<[Buffer][]>> | Order the results according to these functions |
363+
| query.filters | [Array][]<[Function][]([Uint8Array][]) -> [Boolean][]> | Filter the results according to the these functions |
364+
| query.orders | [Array][]<[Function][]([Array][]<[Uint8Array][]>) -> [Array][]<[Uint8Array][]>> | Order the results according to these functions |
365365
| query.limit | [Number][] | Only return this many records |
366366
| query.offset | [Number][] | Skip this many records at the beginning |
367367
| options | [Object][] | An options object, all properties are optional |
@@ -388,7 +388,7 @@ This will return an object with which you can chain multiple operations together
388388
const b = store.batch()
389389

390390
for (let i = 0; i < 100; i++) {
391-
b.put(new Key(`hello${i}`), Buffer.from(`hello world ${i}`))
391+
b.put(new Key(`hello${i}`), new TextEncoder('utf8').encode(`hello world ${i}`))
392392
}
393393

394394
await b.commit()
@@ -402,7 +402,7 @@ Queue a put operation to the store.
402402
| Name | Type | Description |
403403
| ---- | ---- | ----------- |
404404
| key | [Key][] | The key to store the value under |
405-
| value | [Buffer][] | Value to store |
405+
| value | [Uint8Array][] | Value to store |
406406

407407
#### `delete(key)`
408408

@@ -428,7 +428,7 @@ Write all queued operations to the underyling store. The batch object should not
428428
```js
429429
const batch = store.batch()
430430

431-
batch.put(new Key('to-put'), Buffer.from('hello world'))
431+
batch.put(new Key('to-put'), new TextEncoder('utf8').encode('hello world'))
432432
batch.del(new Key('to-remove'))
433433

434434
await batch.commit()
@@ -455,7 +455,7 @@ MIT 2017 © IPFS
455455

456456
[Key]: #Keys
457457
[Object]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object
458-
[Buffer]: https://nodejs.org/api/buffer.html
458+
[Uint8Array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array
459459
[AbortSignal]: https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal
460460
[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator
461461
[AsyncIterable]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols

package.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,14 @@
3333
},
3434
"homepage": "https://github.com/ipfs/interface-datastore#readme",
3535
"devDependencies": {
36-
"aegir": "^22.0.0",
36+
"aegir": "^25.0.0",
3737
"chai": "^4.1.2",
3838
"dirty-chai": "^2.0.1"
3939
},
4040
"dependencies": {
41-
"buffer": "^5.5.0",
4241
"class-is": "^1.1.0",
4342
"err-code": "^2.0.1",
44-
"ipfs-utils": "^2.2.2",
43+
"ipfs-utils": "^2.3.1",
4544
"iso-random-stream": "^1.1.1",
4645
"it-all": "^1.0.2",
4746
"it-drain": "^1.0.1",

src/adapter.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class InterfaceDatastoreAdapter {
1616
* Store the passed value under the passed key
1717
*
1818
* @param {Key} key
19-
* @param {Buffer} val
19+
* @param {Uint8Array} val
2020
* @param {Object} options
2121
* @returns {Promise<void>}
2222
*/
@@ -27,9 +27,9 @@ class InterfaceDatastoreAdapter {
2727
/**
2828
* Store the given key/value pairs
2929
*
30-
* @param {AsyncIterator<{ key: Key, value: Buffer }>} source
30+
* @param {AsyncIterator<{ key: Key, value: Uint8Array }>} source
3131
* @param {Object} options
32-
* @returns {AsyncIterator<{ key: Key, value: Buffer }>}
32+
* @returns {AsyncIterator<{ key: Key, value: Uint8Array }>}
3333
*/
3434
async * putMany (source, options = {}) {
3535
for await (const { key, value } of source) {
@@ -43,7 +43,7 @@ class InterfaceDatastoreAdapter {
4343
*
4444
* @param {Key} key
4545
* @param {Object} options
46-
* @returns {Promise<Buffer>}
46+
* @returns {Promise<Uint8Array>}
4747
*/
4848
async get (key, options = {}) { // eslint-disable-line require-await
4949

@@ -54,7 +54,7 @@ class InterfaceDatastoreAdapter {
5454
*
5555
* @param {AsyncIterator<Key>} source
5656
* @param {Object} options
57-
* @returns {AsyncIterator<Buffer>}
57+
* @returns {AsyncIterator<Uint8Array>}
5858
*/
5959
async * getMany (source, options = {}) {
6060
for await (const key of source) {
@@ -127,7 +127,7 @@ class InterfaceDatastoreAdapter {
127127
*
128128
* @param {Object} q
129129
* @param {Object} options
130-
* @returns {AsyncIterable<{ key: Key, value: Buffer }>}
130+
* @returns {AsyncIterable<{ key: Key, value: Uint8Array }>}
131131
*/
132132
async * _all (q, options) { // eslint-disable-line require-await
133133

@@ -138,7 +138,7 @@ class InterfaceDatastoreAdapter {
138138
*
139139
* @param {Object} q
140140
* @param {Object} options
141-
* @returns {AsyncIterable<Buffer>}
141+
* @returns {AsyncIterable<Uint8Array>}
142142
*/
143143
async * query (q, options) { // eslint-disable-line require-await
144144
let it = this._all(q, options)

src/key.js

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

3-
const { Buffer } = require('buffer')
43
const { nanoid } = require('nanoid')
54
const withIs = require('class-is')
5+
const { utf8Encoder, utf8Decoder } = require('./utils')
6+
const TextDecoder = require('ipfs-utils/src/text-decoder')
67

78
const pathSepS = '/'
8-
const pathSepB = Buffer.from(pathSepS)
9+
const pathSepB = utf8Encoder.encode(pathSepS)
910
const pathSep = pathSepB[0]
1011

1112
/**
@@ -27,9 +28,11 @@ const pathSep = pathSepB[0]
2728
class Key {
2829
constructor (s, clean) {
2930
if (typeof s === 'string') {
30-
this._buf = Buffer.from(s)
31-
} else if (Buffer.isBuffer(s)) {
31+
this._buf = utf8Encoder.encode(s)
32+
} else if (s instanceof Uint8Array) {
3233
this._buf = s
34+
} else {
35+
throw new Error('Invalid key, should be String of Uint8Array')
3336
}
3437

3538
if (clean == null) {
@@ -40,7 +43,7 @@ class Key {
4043
this.clean()
4144
}
4245

43-
if (this._buf.length === 0 || this._buf[0] !== pathSep) {
46+
if (this._buf.byteLength === 0 || this._buf[0] !== pathSep) {
4447
throw new Error('Invalid key')
4548
}
4649
}
@@ -51,16 +54,20 @@ class Key {
5154
* @param {string} [encoding='utf8']
5255
* @returns {string}
5356
*/
54-
toString (encoding) {
55-
return this._buf.toString(encoding || 'utf8')
57+
toString (encoding = 'utf8') {
58+
if (encoding === 'utf8' || encoding === 'utf-8') {
59+
return utf8Decoder.decode(this._buf)
60+
}
61+
62+
return new TextDecoder(encoding).decode(this._buf)
5663
}
5764

5865
/**
59-
* Return the buffer representation of the key
66+
* Return the Uint8Array representation of the key
6067
*
61-
* @returns {Buffer}
68+
* @returns {Uint8Array}
6269
*/
63-
toBuffer () {
70+
uint8Array () {
6471
return this._buf
6572
}
6673

@@ -106,17 +113,20 @@ class Key {
106113
* @returns {void}
107114
*/
108115
clean () {
109-
if (!this._buf || this._buf.length === 0) {
110-
this._buf = Buffer.from(pathSepS)
116+
if (!this._buf || this._buf.byteLength === 0) {
117+
this._buf = pathSepB
111118
}
112119

113120
if (this._buf[0] !== pathSep) {
114-
this._buf = Buffer.concat([pathSepB, this._buf])
121+
const bytes = new Uint8Array(this._buf.byteLength + 1)
122+
bytes.fill(pathSep, 0, 1)
123+
bytes.set(this._buf, 1)
124+
this._buf = bytes
115125
}
116126

117127
// normalize does not remove trailing slashes
118-
while (this._buf.length > 1 && this._buf[this._buf.length - 1] === pathSep) {
119-
this._buf = this._buf.slice(0, -1)
128+
while (this._buf.byteLength > 1 && this._buf[this._buf.byteLength - 1] === pathSep) {
129+
this._buf = this._buf.subarray(0, -1)
120130
}
121131
}
122132

0 commit comments

Comments
 (0)