Skip to content
This repository was archived by the owner on Mar 23, 2023. It is now read-only.

Commit b844c63

Browse files
fix: convert input to buffers before passing to aws-sdk (#30)
* fix: convert input to buffers before passing to aws-sdk The aws-sdk uses the node http client internally which doesn't support Uint8Arrays as data, only [strings or buffers](https://nodejs.org/api/http.html#http_request_end_data_encoding_callback) so convert non-Buffers to Buffers before passing them on. Converts Buffers to Uint8Arrays via no-copy method to remain consistent with other interface-datastore implementations. Updates deps to use latest interface-datastore and aegir. BREAKING CHANGE: - Returns Uint8Arrays only where before it was node Buffers * chore: configure pin store * docs: update example Co-authored-by: Jacob Heun <[email protected]>
1 parent 685fa91 commit b844c63

File tree

7 files changed

+69
-26
lines changed

7 files changed

+69
-26
lines changed

.aegir.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
'use strict'
2+
3+
module.exports = {
4+
webpack: {
5+
node: {
6+
// needed by core-util-is
7+
Buffer: true,
8+
9+
// needed by nofilter
10+
stream: true
11+
}
12+
}
13+
}

examples/full-s3-repo/index.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
const IPFS = require('ipfs')
44
const { createRepo } = require('datastore-s3')
55
const toBuffer = require('it-to-buffer')
6-
const last = require('it-last')
76

87
;(async () => {
98
// Create the repo
@@ -29,10 +28,10 @@ const last = require('it-last')
2928
console.log('Version:', version.version)
3029

3130
// Once we have the version, let's add a file to IPFS
32-
const { path, cid } = await last(node.add({
31+
const { path, cid } = await node.add({
3332
path: 'data.txt',
3433
content: Buffer.from(require('crypto').randomBytes(1024 * 25))
35-
}))
34+
})
3635

3736
console.log('\nAdded file:', path, cid)
3837

examples/full-s3-repo/package.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,8 @@
1212
"dependencies": {
1313
"aws-sdk": "^2.579.0",
1414
"datastore-s3": "../../",
15-
"ipfs": "^0.46.0",
16-
"ipfs-repo": "^3.0.2",
17-
"it-last": "^1.0.2",
15+
"ipfs": "^0.50.2",
16+
"ipfs-repo": "^6.0.3",
1817
"it-to-buffer": "^1.0.2"
1918
}
2019
}

package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,20 +36,20 @@
3636
"homepage": "https://github.com/ipfs/js-datastore-s3#readme",
3737
"dependencies": {
3838
"buffer": "^5.6.0",
39-
"datastore-core": "^1.1.0",
40-
"interface-datastore": "^1.0.2"
39+
"datastore-core": "^2.0.0",
40+
"interface-datastore": "^2.0.0"
4141
},
4242
"devDependencies": {
43-
"aegir": "^24.0.0",
43+
"aegir": "^26.0.0",
4444
"aws-sdk": "^2.579.0",
4545
"chai": "^4.2.0",
4646
"dirty-chai": "^2.0.1",
47-
"ipfs-repo": "^3.0.2",
47+
"ipfs-repo": "^6.0.3",
4848
"stand-in": "^4.2.0"
4949
},
5050
"peerDependencies": {
5151
"aws-sdk": "2.x",
52-
"ipfs-repo": "^3.0.2"
52+
"ipfs-repo": "^6.0.3"
5353
},
5454
"contributors": [
5555
"Jacob Heun <[email protected]>",

src/index.js

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,14 @@ class S3Datastore extends Adapter {
5959
* Store the given value under the key.
6060
*
6161
* @param {Key} key
62-
* @param {Buffer} val
62+
* @param {Uint8Array} val
6363
* @returns {Promise}
6464
*/
6565
async put (key, val) {
6666
try {
6767
await this.opts.s3.upload({
6868
Key: this._getFullKey(key),
69-
Body: val
69+
Body: Buffer.from(val, val.byteOffset, val.byteLength)
7070
}).promise()
7171
} catch (err) {
7272
if (err.code === 'NoSuchBucket' && this.createIfMissing) {
@@ -81,16 +81,24 @@ class S3Datastore extends Adapter {
8181
* Read from s3.
8282
*
8383
* @param {Key} key
84-
* @returns {Promise<Buffer>}
84+
* @returns {Promise<Uint8Array>}
8585
*/
8686
async get (key) {
8787
try {
8888
const data = await this.opts.s3.getObject({
8989
Key: this._getFullKey(key)
9090
}).promise()
9191

92-
// If a body was returned, ensure it's a Buffer
93-
return data.Body ? Buffer.from(data.Body) : null
92+
// If a body was returned, ensure it's a Uint8Array
93+
if (ArrayBuffer.isView(data.Body)) {
94+
if (data.Body instanceof Uint8Array) {
95+
return data.Body
96+
}
97+
98+
return Uint8Array.from(data.Body, data.Body.byteOffset, data.Body.byteLength)
99+
}
100+
101+
return data.Body || null
94102
} catch (err) {
95103
if (err.statusCode === 404) {
96104
throw Errors.notFoundError(err)
@@ -205,13 +213,21 @@ class S3Datastore extends Adapter {
205213
}
206214

207215
for await (const key of it) {
208-
const res = { key }
209-
if (values) {
210-
// Fetch the object Buffer from s3
211-
res.value = await this.get(key)
212-
}
216+
try {
217+
const res = { key }
218+
219+
if (values) {
220+
// Fetch the object Buffer from s3
221+
res.value = await this.get(key)
222+
}
213223

214-
yield res
224+
yield res
225+
} catch (err) {
226+
// key was deleted while we are iterating over the results
227+
if (err.statusCode !== 404) {
228+
throw err
229+
}
230+
}
215231
}
216232
}
217233

@@ -227,7 +243,7 @@ class S3Datastore extends Adapter {
227243
}).promise()
228244
} catch (err) {
229245
if (err.statusCode === 404) {
230-
return this.put(new Key('/', false), Buffer.from(''))
246+
return this.put(new Key('/', false), Uint8Array.from(''))
231247
}
232248

233249
throw Errors.dbOpenFailedError(err)

src/s3-repo.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ const createRepo = (S3Store, options, s3Options) => {
4343
accessKeyId,
4444
secretAccessKey
4545
}),
46-
createIfMissing
46+
createIfMissing,
47+
sharding: true
4748
}
4849

4950
// If no lock is given, create a mock lock
@@ -54,13 +55,15 @@ const createRepo = (S3Store, options, s3Options) => {
5455
root: S3Store,
5556
blocks: S3Store,
5657
keys: S3Store,
57-
datastore: S3Store
58+
datastore: S3Store,
59+
pins: S3Store
5860
},
5961
storageBackendOptions: {
6062
root: storeConfig,
6163
blocks: storeConfig,
6264
keys: storeConfig,
63-
datastore: storeConfig
65+
datastore: storeConfig,
66+
pins: storeConfig
6467
},
6568
lock: lock
6669
})

test/index.spec.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,19 @@ describe('S3Datastore', () => {
4949
return store.put(new Key('/z/key'), Buffer.from('test data'))
5050
})
5151

52+
it('should turn Uint8Arrays into Buffers', () => {
53+
const s3 = new S3({ params: { Bucket: 'my-ipfs-bucket' } })
54+
const store = new S3Store('.ipfs/datastore', { s3 })
55+
56+
standin.replace(s3, 'upload', function (stand, params) {
57+
expect(Buffer.isBuffer(params.Body)).to.be.true()
58+
stand.restore()
59+
return s3Resolve(null)
60+
})
61+
62+
return store.put(new Key('/z/key'), new TextEncoder().encode('test data'))
63+
})
64+
5265
it('should create the bucket when missing if createIfMissing is true', () => {
5366
const s3 = new S3({ params: { Bucket: 'my-ipfs-bucket' } })
5467
const store = new S3Store('.ipfs/datastore', { s3, createIfMissing: true })

0 commit comments

Comments
 (0)