diff --git a/README.md b/README.md index ad056829..f5e46902 100644 --- a/README.md +++ b/README.md @@ -141,7 +141,7 @@ Arguments: * `root` (defaults to [`datastore-fs`](https://github.com/ipfs/js-datastore-fs#readme) in Node.js and [`datastore-level`](https://github.com/ipfs/js-datastore-level#readme) in the browser). Defines the back-end type used for gets and puts of values at the root (`repo.set()`, `repo.get()`) * `blocks` (defaults to [`datastore-fs`](https://github.com/ipfs/js-datastore-fs#readme) in Node.js and [`datastore-level`](https://github.com/ipfs/js-datastore-level#readme) in the browser). Defines the back-end type used for gets and puts of values at `repo.blocks`. * `keys` (defaults to [`datastore-fs`](https://github.com/ipfs/js-datastore-fs#readme) in Node.js and [`datastore-level`](https://github.com/ipfs/js-datastore-level#readme) in the browser). Defines the back-end type used for gets and puts of encrypted keys at `repo.keys` - * `datastore` (defaults to [`datastore-level`](https://github.com/ipfs/js-datastore-level#readme)). Defines the back-end type used as the key-valye store used for gets and puts of values at `repo.datastore`. + * `datastore` (defaults to [`datastore-level`](https://github.com/ipfs/js-datastore-level#readme)). Defines the back-end type used as the key-value store used for gets and puts of values at `repo.datastore`. ```js const repo = new Repo('path/to/repo') diff --git a/src/blockstore-utils.js b/src/blockstore-utils.js new file mode 100644 index 00000000..b1d00f74 --- /dev/null +++ b/src/blockstore-utils.js @@ -0,0 +1,29 @@ +'use strict' + +const base32 = require('base32.js') +const { Key } = require('interface-datastore') +const CID = require('cids') + +/** + * Transform a cid to the appropriate datastore key. + * + * @param {CID} cid + * @returns {Key} + */ +exports.cidToKey = cid => { + const enc = new base32.Encoder() + return new Key('/' + enc.write(cid.buffer).finalize(), false) +} + +/** + * Transform a datastore Key instance to a CID + * + * @param {Key} key + * @returns {CID} + */ +exports.keyToCid = key => { + // Block key is of the form / + const decoder = new base32.Decoder() + const buff = decoder.write(key.toString().slice(1)).finalize() + return new CID(Buffer.from(buff)) +} diff --git a/src/blockstore.js b/src/blockstore.js index 84950f99..27fc5415 100644 --- a/src/blockstore.js +++ b/src/blockstore.js @@ -2,32 +2,10 @@ const core = require('datastore-core') const ShardingStore = core.ShardingDatastore -const Key = require('interface-datastore').Key -const base32 = require('base32.js') const Block = require('ipfs-block') const CID = require('cids') const errcode = require('err-code') - -/** - * Transform a raw buffer to a base32 encoded key. - * - * @param {Buffer} rawKey - * @returns {Key} - */ -const keyFromBuffer = (rawKey) => { - const enc = new base32.Encoder() - return new Key('/' + enc.write(rawKey).finalize(), false) -} - -/** - * Transform a cid to the appropriate datastore key. - * - * @param {CID} cid - * @returns {Key} - */ -const cidToDsKey = (cid) => { - return keyFromBuffer(cid.buffer) -} +const { cidToKey } = require('./blockstore-utils') module.exports = async (filestore, options) => { const store = await maybeWithSharding(filestore, options) @@ -65,7 +43,7 @@ function createBaseStore (store) { if (!CID.isCID(cid)) { throw errcode(new Error('Not a valid cid'), 'ERR_INVALID_CID') } - const key = cidToDsKey(cid) + const key = cidToKey(cid) let blockData try { blockData = await store.get(key) @@ -78,7 +56,7 @@ function createBaseStore (store) { throw err } - const otherKey = cidToDsKey(otherCid) + const otherKey = cidToKey(otherCid) const blockData = await store.get(otherKey) await store.put(key, blockData) return new Block(blockData, cid) @@ -98,7 +76,7 @@ function createBaseStore (store) { throw new Error('invalid block') } - const k = cidToDsKey(block.cid) + const k = cidToKey(block.cid) const exists = await store.has(k) if (exists) return return store.put(k, block.data) @@ -112,7 +90,7 @@ function createBaseStore (store) { */ async putMany (blocks) { const keys = blocks.map((b) => ({ - key: cidToDsKey(b.cid), + key: cidToKey(b.cid), block: b })) @@ -141,11 +119,11 @@ function createBaseStore (store) { throw errcode(new Error('Not a valid cid'), 'ERR_INVALID_CID') } - const exists = await store.has(cidToDsKey(cid)) + const exists = await store.has(cidToKey(cid)) if (exists) return exists const otherCid = cidToOtherVersion(cid) if (!otherCid) return false - return store.has(cidToDsKey(otherCid)) + return store.has(cidToKey(otherCid)) }, /** * Delete a block from the store @@ -157,7 +135,7 @@ function createBaseStore (store) { if (!CID.isCID(cid)) { throw errcode(new Error('Not a valid cid'), 'ERR_INVALID_CID') } - return store.delete(cidToDsKey(cid)) + return store.delete(cidToKey(cid)) }, /** * Close the store diff --git a/src/index.js b/src/index.js index e19fae99..5b203be2 100644 --- a/src/index.js +++ b/src/index.js @@ -298,6 +298,7 @@ async function getSize (queryFn) { } module.exports = IpfsRepo +module.exports.utils = { blockstore: require('./blockstore-utils') } module.exports.repoVersion = repoVersion module.exports.errors = ERRORS diff --git a/test/blockstore-utils-test.js b/test/blockstore-utils-test.js new file mode 100644 index 00000000..3bea8544 --- /dev/null +++ b/test/blockstore-utils-test.js @@ -0,0 +1,22 @@ +/* eslint-env mocha */ +'use strict' + +const chai = require('chai') +chai.use(require('dirty-chai')) +const { expect } = chai +const { Key } = require('interface-datastore') +const CID = require('cids') +const Repo = require('../src') + +module.exports = () => { + describe('blockstore utils', () => { + it('converts a CID to a datastore Key and back', () => { + const originalCid = new CID('Qme6KJdKcp85TYbLxuLV7oQzMiLremD7HMoXLZEmgo6Rnh') + const key = Repo.utils.blockstore.cidToKey(originalCid) + expect(key instanceof Key).to.be.true() + const cid = Repo.utils.blockstore.keyToCid(key) + expect(cid instanceof CID).to.be.true() + expect(originalCid.toString()).to.equal(cid.toString()) + }) + }) +} diff --git a/test/browser.js b/test/browser.js index 92981754..b5f61670 100644 --- a/test/browser.js +++ b/test/browser.js @@ -19,6 +19,7 @@ describe('IPFS Repo Tests on the Browser', () => { require('./repo-test')(repo) require('./blockstore-test')(repo) + require('./blockstore-utils-test')() require('./datastore-test')(repo) require('./keystore-test')(repo) require('./config-test')(repo) diff --git a/test/node.js b/test/node.js index da78e3bb..9fd46ca7 100644 --- a/test/node.js +++ b/test/node.js @@ -103,4 +103,6 @@ describe('IPFS Repo Tests onNode.js', () => { require('./interop-test')(repo) } })) + + require('./blockstore-utils-test')() })